2020年2月20日OJ习题【string】

在C语言中,一般使用字符数组char str[]来存放字符 串,但是操作麻烦,容易出错。C++在STL中加入了string类 型,对字符串常用的需求功能进行了封装,使得操作起来更 加方便,且不必担心内存是否足够、字符串的长度等问题。 使用string,需要添加string头文件,即#include < string >, 同时必须要有“using namespace std”。 定义string的方法为:string name; 其中,name是字符串变量的名字。例如:string str;也可 以定义的同时初始化,即:string str=“abcd”。

1. string 的访问
一种访问 string 的方法,就像普通字符数组一样操作。 例如:
string str= “ abcd “ ;
for(int i = 0; i < str.length(); i++)
printf( “ %c “ ,str[i]); // 输出 abcd 如果要读入或者输出整个字符串,一般只能用cin和 cout。如果非要用printf输出string,则需要用c_str()函数将 string转换成字符数组。
例如: string str; cin>>str; cout<<str<<endl; printf("%s\n",str.c_str());
另一种访问string的方法是通过迭代器,主要与insert()、 erase()等函数配合使用。
先定义string迭代器:
string::iterator it;
然后就可以通过“*it”来访问string里的每一个字符了, 而且string和vector一样,支持直接对迭代器进行加减某个数 字,如str.begin()+3等。
例如:
string str=“abcdefg”;
for(string::iterator it = str.begin()+2; it != str.end(); it++)
printf("%c",*it);//输出cdefg

2. string 的运算
字符串可以做“加法”运算。加法是把两个字符串直接 拼接起来。
例如:
string str1= “ abc “ ,str2= “ xyz “ ,str3;
str3 = str1 + str2;
str1 += str2;
cout << str1 << endl;// 输出 abcxyz
cout << str3 << endl;// 输出 abcxyz
字符串还可以做“关系”运算,是按照字典序比较两个 string 类型的大小。例如:
string str1= “ aa “ ,str2= “ aaa “ ,str3= “ abc “ ;
if(str1 < str2) printf( “ OK1 “ );// 输出 OK1
if(str1 < str3) printf( “ OK2 “ );// 输出 OK2

3. string 的常用函数
(1)length()和size()
length()用来返回 string 的长度(字符个数),时间复杂度为O(1)。 size()与 length()一样。
(2)clear()
clear()用来清空 string 中的所有元素,时间复杂度为O (1)。
(3)substr()
Substr(pos,len)返回从 pos 号位置开始、长度为 len 的子串,时间复 杂度为O (n)。
(4)insert ()
函数 insert ()有多种写法,时间复杂度都是O (n)。insert(pos,string), 表示在pos号位置插入字符串string。insert(it,it2,it3),it为原字符串的欲 插入位置,it2和it3为待插入字符串的首尾迭代器(左闭右开区间)。
(5)erase()
erase()可以删除单个元素,也可以删除一个区间内的所 有元素,时间复杂度均为O (n)。删除单个元素用erase(it), it为要删除的元素的迭代器。删除一个区间内的所有元素可 以用两种方法。erase(first,last),first为区间的起始迭代器, last为区间的末尾迭代器的下一个地址,也就是左闭右开的 区间[first,last)。erase(pos,length),pos为需要删除的字 符串起始位置,length为要删除的字符个数。
(6)find()
str.find(str2),当str2是str的子串时,返回其在str中第 一次出现的位置;否则返回string::npos。string::npos是一 个常数,其本身的值等于-1,但由于是unsigned int类型, 因此,也可以认为是unsigned int类型的最大值 (4294967295)。str.find(str2,pos),是从str的pos号位开始 匹配str2,返回值同str.find(str2)。以上两种写法的时间复 杂度都是O(n*m),其中n和m分别为str和str2的长度。
(7)replace()
str.replace(pos,len,str2)表示把str从pos号位开始、长度 为len的子串替换为str2。也可以写成str.replace(it1,it2,str2), 表示把str的迭代器it1~it2范围内(左闭右开区间)的子串替 换为str2。时间复杂度都是O(str.length)。时间复杂度都是 O(str.length)。

字符串合并-string

#include <bits/stdc++.h>
using namespace std;
string str,str1,str2;
int main()
{
    while(cin>>str1>>str2)
    {
        str=str1+str2;
        cout<<str<<endl;
    }
    return 0;
}

回文字符串-string

#include <bits/stdc++.h>
using namespace std;
string a,b;
int n;
int main()
{
    cin>>n;
    while(n--)
    {
        cin>>a;
        int l=a.length();
        b=a;
        reverse(a.begin(),a.begin()+l);
        if(a==b)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}

气球-string-map

用map记录同一颜色的气球数

#include <bits/stdc++.h>
using namespace std;
int n;
string color,tmp;
map<string,int>vis;
map<string,int>::iterator it;
int main()
{
    while(cin>>n&&n)
    {
        int ans=0;
        vis.clear();
        while(n--)
        {
            cin>>color;
            vis[color]++;
            if(vis[color]>ans)
                ans=vis[color];
        }
        for(it=vis.begin();it!=vis.end();it++)
        {
            tmp=(*it).first;
            if(ans==vis[tmp])
            {
                cout<<tmp<<endl;
                break;
            }
        }
    }
    return 0;
}

取子字符串-string

#include <bits/stdc++.h>
using namespace std;

string str;
int m,n;
int main()
{
    while(cin>>str>>n>>m)
    {
        str=str.substr(n-1,m-n+1);
        cout<<str<<endl;
    }
    return 0;
}

strange string

这题有坑,必须是连续的相同字符才会计数,比如abcabc这样的其实是NO的,而aabbcc的才是YES;
但是自己修改后的写法总是WA
这是错误的代码

#include <bits/stdc++.h>
using namespace std;
char str[12];
int a[10];
int main()
{
    while(cin>>str+1)
    {
        int l=strlen(str+1);
        memset(a,0,sizeof(a));
        int ans=1;
        a[ans]++;
        for(int i=2;i<l+1;i++)
        {
            if(str[i]==str[i-1])
                a[ans]++;
            else
                a[++ans]++;
        }
        if(ans!=3||(a[1]!=a[2]||a[1]!=a[3]||a[2]!=a[3]))
            cout<<"NO"<<endl;
        else
            cout<<"YES"<<endl;
    }
    return 0;
}

上述代码,错误的原因是,只考虑了连续的字母是不同的,没考虑到可能第一种字母与第三种字母是相同的情况下,即aabbaa,这应该是错误的,但是这个代码会认为是正确的,所以这种写法还要再加一个判断,去判断是否有三种字母,如下

#include <bits/stdc++.h>
using namespace std;
string str;
char ch[3];
int a[10];
int main()
{
    while(cin>>str)
    {
        int l=str.length();
        memset(a,0,sizeof(a));
        memset(ch,'0',sizeof(ch));
        int ans=1,cnt=1;
        a[ans]++;
        ch[cnt]=str[0];
        for(int i=1;i<l;i++)
        {
            if(str[i]==str[i-1])
                a[ans]++;
            else
            {
                a[++ans]++;
                ch[++cnt]=str[i];
            }
        }
        int flag=1;
        if(cnt!=3||ans!=3||(a[1]!=a[2]||a[1]!=a[3]||a[2]!=a[3])||(ch[1]==ch[2]||ch[1]==ch[3]||ch[2]==ch[3]))//这里如果有两种字母是一样的,flag也是0
           flag=0;
        if(flag==1)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}

还有一种非常暴力的方法,根据题意,满足条件的字符串长度只会是3,6,9,因此知道把这三种满足条件的情况都写出来去判断就好了,也就是纯模拟

#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    string str;
    while(cin>>str)
    {
        bool flag = 0;
        if(str.size()==3)//满足题意的字符串长度只有3,6,9三种情况
        {
            if(str[0]!=str[1] && str[1]!=str[2] && str[0]!=str[2])
                flag = 1;
        }
        else if(str.size()==6)
        {
            if(str[0]==str[1] && str[2]==str[3] && str[4]==str[5])
                if(str[1]!=str[2] && str[3]!=str[4] && str[1]!=str[4])
                    flag = 1;
        }
        else if(str.size()==9)
        {
            if((str[0]==str[1]&&str[1]==str[2])&&(str[3]==str[4]&&str[4]==str[5])&&(str[6]==str[7]&&str[7]==str[8]))
                if(str[0]!=str[3] && str[3]!=str[6] && str[0]!=str[6])
                    flag = 1;
        }
        else flag = 0;
        if(flag) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

下面三道题,都属于暴力找答案的思想

字符串处理-string

这个就暴力把每一部分字符串都反转后看是不是与原来的字符串相同,相同就计数

#include <bits/stdc++.h>
using namespace std;
string str,ch;
int i,j,l;
int main()
{
    while(cin>>str)
    {
        l=str.length();
        int ans=0;
        for(i=0;i<l;i++)//遍历反转起点
        {
            for(j=i+1;j<=l;j++)//遍历反转终点
            {
                ch=str;
                reverse(ch.begin()+i,ch.begin()+j);//反转
                if(str==ch)
                    ans++;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

字符串乘方-string

这题的意思就是看整个串是不是其中某一部分(从str[0]开始)的多次循环所构成的

#include <bits/stdc++.h>
using namespace std;
string str,str1,str2;
int ans,maxn;
int main()
{
    while(cin>>str)
    {
        if(str==".") break;
        int l=str.length();
        ans=1;
        maxn=0;
        int i=0;
        for(int j=1;j<=l;j++)
        {
            str2.clear();
            str2=str.substr(i,j);//取出循环串
            str1=str2;
            while(1)//循环叠加串
            {
                if(str2.length()>=str.length()&&str2!=str)//如果到了原字符串的长度还不是与原字符串相同,就不是这个串的循环
                {
                    ans=1;
                    break;
                }
             if(str2==str)//如果是这个串的循环,还要找循环的次数是不是最多
                {
                    maxn=max(maxn,ans);
                    ans=1;
                    break;
                }
            ans++;//记录循环的次数,即目标的n
            str2+=str1;//叠加
            }
        }
        cout<<maxn<<endl;
    }
    return 0;
}

字符串匹配-string

这题一开始有两点没考虑到
1.只考虑了用短的串去匹配长的,但是还应该把长的匹配短的,比如这种情况: bdefgh
abdf
这样的话,只用短的匹配长的就会WA;
2.有可能会出现两个串相同的情况,那样的话用特判

#include <bits/stdc++.h>
using namespace std;
string str1,str2;
int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
    while(cin>>str1&&str1!="-1")
    {
        cin>>str2;
        int ans=0,maxn=0;
        int la=str1.length(),lb=str2.length();
        int l=la+lb;
        for(int i=0;i<la;i++)
        {
            int j=i,t=0;
            ans=0;
            while(1)
            {
                if(str1[j]==str2[t]) ans+=2;
                j++,t++;
                if(j==la||t==lb)
                    break;
            }
            if(maxn<ans)
                maxn=ans;
        }
        for(int i=0;i<lb;i++)
        {
            int j=i,t=0;
            ans=0;
            while(1)
            {
                if(str2[j]==str1[t]) ans+=2;
                j++,t++;
                if(j==lb||t==la)
                    break;
            }
            if(maxn<ans)
                maxn=ans;
        }
        if(maxn==0)//找不到相同的特判
            printf("appx(%s,%s) = %d\n",str1.c_str(),str2.c_str(),0);
        else if(maxn==l)//两个串相同的特判
            printf("appx(%s,%s) = %d\n",str1.c_str(),str2.c_str(),1);
        else
        {
            int x=gcd(l,maxn);
            maxn=maxn/x;
            l=l/x;
            printf("appx(%s,%s) = %d/%d\n",str1.c_str(),str2.c_str(),maxn,l);
        }
    }
    return 0;
}

祝愿后天考试顺利。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值