字符串专题
1.统计单词频率
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;
int main()
{
string str;
while(getline(cin,str)){
int hashTable[26]={0};
int maxn=-1;
for(int i=0;i<str.size();i++){
if(isalpha(str[i])){
str[i]=tolower(str[i]);
hashTable[str[i]-'a']++;
maxn=max(maxn,hashTable[str[i]-'a']);
}
}
for(int i=0;i<26;i++){
if(hashTable[i]==maxn){
printf("%c %d\n",i+'a',maxn);
}
}
}
return 0;
}
#include <iostream>
#include <string>
#include <vector>
#include <ctype.h>
#include <cmath>
using namespace std;
int main()
{
string str;
int hashTable[26]={0};
int anum=0,wnum=0,cntMax=0;
while(cin>>str){
anum=anum+str.size();
wnum++;
for(int i=0;i<str.size();i++){
str[i]=tolower(str[i]);
hashTable[str[i]-'a']++;
cntMax=max(cntMax,hashTable[str[i]-'a']);
}
//这个要用对地方!!,用在前面没处理,少读字符串
char ch=getchar();
if(ch=='\n') break;
}
printf("字母个数:%d\n",anum);
printf("单词个数:%d\n",wnum);
bool nofirst=false;
printf("最多的字母:");
for(int i=0;i<26;i++){
if(hashTable[i]==cntMax){
if(nofirst){
printf(",%c",i+'a');
}else{
nofirst=true;
printf("%c",i+'a');
}
}
}
printf("\n出现的次数:%d\n",cntMax);
return 0;
}
2.密文加密
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;
int main()
{
string str;
while(getline(cin,str)){
for(int i=0;i<str.size();i++){
if(isalpha(str[i])){
if(islower(str[i])){
str[i]=(str[i]+3-'a')%26+'a';
}else{
str[i]=(str[i]+3-'A')%26+'A';
}
}
}
cout<<str<<endl;
}
return 0;
}
cctype头文件中处理字符函数
[图片上传失败...(image-578378-1587804682906)]
3.find使用,删除指定子串,transform使用
对于字符串string,需要使用string头文件,包含以下常用方法:
s.find(str,[pos]):在字符串s中从第 pos 个字符开始寻找 str ,并返回位置,如果找不到返回-1。pos 可省略,默认为0
s.erase(pos,n):从给定起始位置 pos 处开始删除,要删除字符的长度为n,返回修改后的string对象
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;
int main()
{
string str;
while(cin>>str){
int pos=0;
string word="gzu";
//果然字符串还是得要用双引号稳妥,pos放在下面也更稳妥
while(str.find(word,pos)!=string::npos){
pos=str.find(word,pos);
str.erase(pos,3);
}
cout<<str<<endl;
}
return 0;
}
//进阶版
int main()
{
string str;
while(cin>>str){
int pos=0;
string word="gzu";
string temp=str;
transform(str.begin(),str.end(),str.begin(),::tolower);
//while ((pos = str1.find("gzu")) != -1)也可!!
while(str.find(word,pos)!=string::npos){
pos=str.find(word,pos);
str.erase(pos,3);
temp.erase(pos,3);
}
cout<<temp<<endl;
}
return 0;
}
4.字符串前缀识别
#include <iostream>
#include<string.h>
using namespace std;
int main()
{
char str[100][100];
int n;
while (cin >> n&& n)
{
for (int i = 0; i < n; i++)
{
cin >> str[i];
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i == j)continue;//比较不同字符串
if (str[i][0] == '@')continue;//已经修改过的就不用再判断了
bool flag = true;
for (int k = 0; k < strlen(str[i])&& flag; k++)
{
if (str[i][0] == '@')
flag = false;
if (str[i][k] != str[j][k])
flag = false;
}
if (flag)
{
str[i][0] = '@';
}
}
}
int ans = 0;
for (int i = 0; i < n; i++)
{
if (str[i][0] != '@')
ans++;
}
cout << ans << endl;
}
return 0;
}
给定字符串找出重复字符和位置,*号法
/*对于给定字符串,找出有重复的字符,并给出其位置*/
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(){
string str;
while(cin>>str){
int len=str.size();
for(int i=0;i<len-1;i++){
bool first=true;
bool isDup=false;
if(str[i]!='*'){
//i.j不要老搞错
for(int j=i+1;j<len;j++){
if(str[i]==str[j]){
isDup=true;
str[j]='*';
if(first){
cout<<str[i]<<","<<i+1<<";"<<str[i]<<","<<j+1;
first=false;
}else{
cout<<";"<<str[i]<<","<<j+1;
}
}
}
}
if(isDup){
cout<<endl;
}
}
}
}
5.string循环截取的两种办法
//记录当前位置截取法,有当前位置和新位置,不改变原来字符串
void CutString(string line,vector<string> &subline,char a){
//a就是截取的标号
size_t pos=0;
while(pos<line.length()) {
size_t curpos=pos;
pos=line.find(a,curpos);
if(pos==string::npos)
{
pos=line.length();
}
subline.push_back(line.substr(curpos,pos-curpos));
pos++;
}
}
//查找截取之后删除法,不管咋样,pos还是不要放在判定中
while(str.find('.')!=-1){
//观念一直没有改过来,pos是位置,pos-0就是长度,0-pos长度就是pos+!
//pos用法果然有问题
pos=str.find('.');
//下面逻辑没得问题
temp=str.substr(0,pos);
arr.push_back(temp);
str=str.erase(0,pos+1);
}
arr.push_back(str);
6.读入用户输入的,以“.”结尾的一行文字,统计一共有多少个单词
2、 #include<stdio.h>
3、 #include<string.h>
4、 int main(){
5、 char s[1000];
6、 int len,a[1000]={0},i,cnt;
7、 gets(s);
8、 len=strlen(s);
9、 printf("len=%d\n",len);
10、 cnt=0;//记录单词数;
11、 i=0;
//如果是这样计算就不要老想着for循环,while自己i++
12、 while(i<len-1&&s[i]==' '){//去掉开头的空格;
13、 i++;
14、 }
15、 while(i<len-1){
16、 if(s[i]!=' '){//遇到字符;
17、 a[cnt]+=1;
18、 i++;
19、 }
20、 else{//遇到空格;
21、 cnt++;//下一个单词;
22、 while(i<len-1&&s[i]==' '){//去掉中间的连续空格;
23、 i++;
24、 }
25、 }
26、 }
27、 printf("单词个数:%d.\n",cnt+1);
28、 printf("每个单词所含有的字符数是:\n");
29、 for(i=0;i<cnt+1;i++){
30、 printf("%d ",a[i]);
31、 }
32、 }
7.找出数组中最长无重复子串的长度
/*
输出一个整数,代表arr的最长无重复字符的长度。
不要和最长公共子串搞混,这个就是自己的子串
*/
#include<iostream>
using namespace std;
int A[100001];
int main() {
int n; int length = 0;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> A[i];
}
int start = 0; int i = 1;
while (i < n) {
int temp = 1;
for (int j = start; j < i; j++) {
if (A[j] == A[i]) {
start = j + 1;
}
else {
temp++;
}
if (temp > length)length = temp;
}
i++;
}
cout << length;
return 0;
}
方法二:
#include<iostream>
#include<unordered_set>
using namespace std;
int main()
{
int n;
cin>>n;
int *arr = new int[n];
for(int i = 0; i<n; i++)
{
int temp;
cin>>temp;
arr[i] = temp;
}
int length =0;
int left = 0;
int right = 0;
unordered_set<int> rec;
while (left < n && right < n)
{
int cur = arr[right];
//终于明白了,end()相当于a[n]指向最后一个后一个元素
if (rec.end() == rec.find(cur))
{
rec.insert(cur);
right++;
length = (right - left) > length?(right - left):length;
}
else
{ //没有指向最后一个,也就是说找到了!!,这个意思也就是起点需要后移
//如果一直都是找到的,那么就得一直后移
rec.erase(arr[left]);
left++;
}
}
cout<<length<<endl;
delete [] arr;
return 0;
}
8.手机键盘按键,find和hash办法
/*
手机键盘
*/
#include <iostream>
using namespace std;
int main()
{
string arr[8]={"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
string str;
while(cin>>str){
int cnt=0;
for(int i=0;i<str.size();i++){
int pos;
for(int j=0;j<8;j++){
if(arr[j].find(str[i])!=-1){
//找到的意思
pos=arr[j].find(str[i]);
if(i+1<str.size()&&arr[j].find(str[i+1])!=-1){
cnt=cnt+2;
}
}
}
cnt=cnt+pos+1;
}
cout<<cnt<<endl;
}
return 0;
}
好方法:
1其实只需要一个数组就够用了啊。用key顺序记录26个字母按键次数,
2然后判断两个字母是否在同一个按键上,如果在同一个按键上,那么下标差(字母间距)
就等于按键次数差。
#include<iostream>
#include<string>
using namespace std;
int main()
{
int key[26] = {1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,4,1,2,3,1,2,3,4};
string str;
while(cin>>str)
{
int count = key[str[0]-'a'];
for(int i=1;i<str.size();++i)
{
count += key[str[i]-'a'];
if(key[str[i]-'a']-key[str[i-1]-'a']==str[i]-str[i-1])//判断是否在同一个按键上
count+=2;
}
cout<<count<<endl;
}
}
9.给定一个0字符串,求出全部子串出现次数
/*map方法,自动按照字典序增序
使用substr轻松截取子串,为啥老是忘记了!!*/
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s;
while(cin>>s){
map<string,int> m;
for(int i=0;i<=s.size();i++){
for(int j=0;j<i;j++){
m[s.substr(j,i-j)]++;
}
}
for(auto it=m.begin();it!=m.end();it++){
if(it->second>1)
cout<<it->first<<" "<<it->second<<endl;
}
}
return 0;
}
方法二:朴素手写方法
//一前一后两个指针来截取子串
#include <iostream>
#include <bits/stdc++.h>
#define N 5050
using namespace std;
struct STR{
string s;
unsigned cnt;
}buf[N]; //子串集合
int n; //子串数量
string str; //读取的字符串
string child; //临时存储子串
void MakeChild(int from,int len){
child.clear();
for(int i=0;i<len;i++){
//果然在于这里的处理方式
child=child+str[from+i];
}
}
bool cmp(STR a,STR b){
return a.s<b.s;
}
void letsGo(){
//生成子串列表并完成统计
int len=str.size();
for(int i=1;i<len;i++){
//i是子串长度
for(int from=0;from+i<=len;from++){
MakeChild(from,i); //生成子串
bool repeat=false; //用来检查这个子串以前是否出现
for(int i=0;i<n;i++){
if(buf[i].s==child){
buf[i].cnt++;
repeat=true;
break;
}
}
if(!repeat){
//这个字串以前没有出现过
buf[n].cnt=1;
buf[n].s=child;
n++;
}
}
}
}
int main()
{
while(cin>>str){
n=0; //子串个数
letsGo();
sort(buf,buf+n,cmp);
for(int i=0;i<n;i++){
if(buf[i].cnt>1){
cout<<buf[i].s<<" "<<buf[i].cnt<<endl;
}
}
}
return 0;
}