第五讲 字符串

目录

  • 1. 基础知识
  • 2.练习题
    • 2.1 字符串长度
    • 2.2 字符串中的数字个数
    • 2.3 循环相克令
      • 2.3.1 分析
    • 2.4 字符串加空格
    • 2.5 替换字符
    • 2.6 字符串插入
    • 2. 7 只出现一次的字符
    • 2.8 字符串匹配
    • 2.9 忽略大小写比较字符串大小
    • 2.10 去掉多余的空格
    • 2.11 信息加密
    • 2.12 输出字符串
    • 2.13 单词替换
    • 2.14 字符串中最长的连续出现的字符
    • 2.15 最长单词
    • 2.16 倒排单词
    • 2.17 字符串移位包含问题
    • 2.18 字符串乘方
    • 2.19 字符串最大跨距
    • 2.20 最长公共字符串后缀

1. 基础知识

1.字符和整数可以相互转化,例如

#include 
using namespace std;

int main()
{
 	char a1[] = {'C', '+', '+'};
	cout <<"a1:" << a1 << " size:" << sizeof(a1) << endl;
	char a2[] = {'C', '+', '+', '\0'};
	cout <<"a2:" << a2 << " size:" << sizeof(a2) << endl;
	//报错
	//char a3[3] = {'C', '+', '+', '\0'};
	//cout << "a3:" << a3 << " size:" << sizeof(a3) << endl;
	char a4[6] = {'C', '+', '+', '\0'};
	cout << "a4:" << a4 << " size:" << sizeof(a4) << endl;
   return 0;
}

2.字符串就是字符数组加’\0’
3.c++中的零特别灵活,int里是0,字符串里是‘\0’,指针是null,bool里是false。相互等价。
4.字符串的输入与输出

#include 
using namespace std;
int main()
{
	char a[100];
	//遇到空格就结束输入
	scranf("%s", a);
	cout << a << endl;
	//puts自动加换行
	puts(a);
	return 0;
}

5.数据类型为char数组
最简单的写法

#include 
using namespace std;
int main()
{
	char s[10];
	cin >> s;
	return 0;
} 

符串数组输入gets不安全,使用fgets(),优点是安全并且输入了空格.fgets()并不把回车自动过滤的。

#include 
using namespace std;

int main()
{
	char a[100];
	//第一个参数存储地址,第二个参数最大存储单位,第三个参数是从哪里获得字符串
	//stdin是系统变量,把标准读入当文件,接受来自键盘的输入
	fgets(a, 100, stdin);
	cout << a  << endl;
	return 0;
}
#include 
using namespace std;

int main()
{
   char s[100];
	cin.getline(s, 100);
	cout << s << endl;
   return 0;
}

6.数据类型为string。
getline输入数据要string类型

#include 
using namespace std;

int main()
{
	string s;
    getline(cin, s);
	cout << s  << endl;
	return 0;
}

7.字符串常用函数
头文件string.h,可以发现这是一个c文件

strlen()
//a < b,返回-1;a == b, 返回0;a > b,返回1。这里比较的方式是字典序列,字典序跟贪心有关
strcmp(a, b)
//把字符串b复制给字符串a
strcpy(a, b)

8.输入的字符串没有空格,用cin和scanf;如果有空格,用fgets、getline和cin.getlines
9.字符串库string,不能用scanf读入,可以用printf输出printf("%s\n",s1.c_str())
10.字符串输入getline(cin, s)cin.getline(s, 100)有空也可以使用;cin的话只能读入第一个空格前的字符串
11.检查字符串是否为空s1.empty(),如果为空返回1,如果有东西返回0;s1.size()返回的是字符串的长度,时间复杂度是O(1)的,里面有个变量专门存储字符串的长度,而strlen的时间复杂度是O(n)的;
12.String类的对象支持相加,比大小
13.String类的对象for循环有种特别的写法

#include 
using namespace std;
int main()
{
	string s = "hello world!";
	for(char c: s) cout << c << endl;
	return 0;
}
#include 
using namespace std;
int main()
{
	string s = "hello world!";
	for(char c: s)
	{
		c = '+';
	}
	puts(s.c_str());//输出字符串没有发生改变
	return 0;
}
#include 
using namespace std;
int main()
{
	string s = "hello world";
	for(auto &c: s)//auto能猜出数据类型
	{
		c = '+';
	}
	puts(s.c_str());
	return 0;
}

2.练习题

2.1 字符串长度

给定一行长度不超过 100 的非空字符串,请你求出它的具体长度。

输入格式
输入一行,表示一个字符串。注意字符串中可能包含空格。

输出格式
输出一个整数,表示它的长度。

输入样例:
I love Beijing.
输出样例:
15

#include 
#include 
using namespace std;

int main()
{
    string s;
    getline(cin, s);
    
    int len = 0;
    for(auto c : s) len ++;
    
    cout << len << endl;
    return 0;
}

2.2 字符串中的数字个数

输入一行字符,长度不超过 100,请你统计一下其中的数字字符的个数。

输入格式
输入一行字符。注意其中可能包含空格。

输出格式
输出一个整数,表示字数字字符的个数。

输入样例:
I am 18 years old this year.
输出样例:
2

#include 
#include 
using namespace std;
int main()
{
    string s;
    getline(cin, s);
    
    int len = 0;
    for(auto c: s)
    {
        if(c >= '0' && c <= '9') len ++;
    }
    
    cout << len << endl;
    return 0;
}

2.3 循环相克令

循环相克令是一个两人玩的小游戏。

令词为“猎人、狗熊、枪”,两人同时说出令词,同时做出一个动作——猎人的动作是双手叉腰;狗熊的动作是双手搭在胸前;枪的动作是双手举起呈手枪状。

双方以此动作判定输赢,猎人赢枪、枪赢狗熊、狗熊赢猎人,动作相同则视为平局。

现在给定你一系列的动作组合,请你判断游戏结果。

输入格式
第一行包含整数 T,表示共有 T 组测试数据。

接下来 T 行,每行包含两个字符串,表示一局游戏中两人做出的动作,字符串为 Hunter, Bear, Gun 中的一个,这三个单词分别代表猎人,狗熊和枪。

输出格式
如果第一个玩家赢了,则输出 Player1。

如果第二个玩家赢了,则输出 Player2。

如果平局,则输出 Tie。

数据范围
1≤N≤100
输入样例
3
Hunter Gun
Bear Bear
Hunter Bear
输出样例
Player1
Tie
Player2

2.3.1 分析

此题十分有意义。两个人玩游戏,一个人令词有3种,也就是总共有9种情况。不优化的编程需要写9条if规则。优化的算法,对词令进行编码。

#include 
#include 
using namespace std;

int main()
{
    string s1, s2;
    int c1, c2;
    int n;
    cin >> n;
    
    while(n --)
    {
        cin >> s1 >> s2;
        
        if(s1 == "Hunter") c1 = 0;
        else if(s1 == "Bear") c1 = 1;
        else if(s1 == "Gun") c1 = 2;
        
        if(s2 == "Hunter") c2 = 0;
        else if(s2 == "Bear") c2 = 1;
        else if(s2 == "Gun") c2 = 2;
        
        
        if(c1 == c2) puts("Tie");
        else if(c1 == (c2 + 1) % 3) puts("Player1");
        else puts("Player2");
        
    }
    return 0;
}

2.4 字符串加空格

给定一个字符串,在字符串的每个字符之间都加一个空格。

输出修改后的新字符串。

输入格式
共一行,包含一个字符串。注意字符串中可能包含空格。

输出格式
输出增加空格后的字符串。

数据范围
1≤字符串长度≤100
输入样例:
test case
输出样例:
t e s t c a s e

#include 
#include 
using namespace std;
int main()
{
    string s1, s2;
    getline(cin, s1);
    
    for(auto c: s1)
    {
        s2 = s2 + c + ' ';
    }
    //s2.pop_back();//把最后一个字符删除
    puts(s2.c_str());
    return 0;
}

2.5 替换字符

给定一个由大小写字母构成的字符串。

把该字符串中特定的字符全部用字符 # 替换。

请你输出替换后的字符串。

输入格式
输入共两行。

第一行包含一个长度不超过 30 的字符串。

第二行包含一个字符,表示要替换掉的特定字符。

输出格式
输出共一行,为替换后的字符串。

输入样例:
hello
l
输出样例:
he##o

#include 
using namespace std;

int main()
{
    char a[31];
    cin >> a;
    char c;
    cin >> c;
    
    for(int i = 0; a[i] != '\0'; i ++)
    {
        if(a[i] == c) a[i] = '#';
    }
    
    puts(a);
    return 0;
}

2.6 字符串插入

有两个不包含空白字符的字符串 str 和 substr,str 的字符个数不超过 10,substr 的字符个数为 3。(字符个数不包括字符串结尾处的 \0。)

将 substr 插入到 str 中 ASCII 码最大的那个字符后面,若有多个最大则只考虑第一个。

输入格式
输入包括若干行,每一行为一组测试数据,格式为

str substr

输出格式
对于每一组测试数据,输出插入之后的字符串。

输入样例:
abcab eee
12343 555
输出样例:
abceeeab
12345553

#include 
#include 
using namespace std;

int main()
{
    string s1, s2;
    while(cin >> s1 >> s2)
    {
        int max_tmp = -9999;
        int flag = 0;
        for(int i = 0; s1[i]; i ++)
        {
            if(s1[i] > max_tmp) max_tmp = s1[i], flag = i;
        }
    	//C++的字符拼接函数substr()
        cout << s1.substr(0, flag + 1) + s2 + s1.substr(flag + 1) << endl;    
    }
    return 0;
}

2. 7 只出现一次的字符

给你一个只包含小写字母的字符串。

请你判断是否存在只在字符串中出现过一次的字符。

如果存在,则输出满足条件的字符中位置最靠前的那个。

如果没有,输出 no。

输入格式
共一行,包含一个由小写字母构成的字符串。

数据保证字符串的长度不超过 100000。

输出格式
输出满足条件的第一个字符。

如果没有,则输出 no。

输入样例:
abceabcd
输出样例:
e

#include 
#include 
using namespace std;
//大数组放在主函数外,在堆中开辟内存。主程序的栈空间不是很大。
char s[100010];
int main()
{
	//状态数组标记字符出现过几次
    int a[27] = {0};
    
    
    scanf("%s", s);
    
    int tmp = 0;
    for(int i = 0; s[i] != '\0'; i ++)
    {
        tmp = s[i] - 'a';
        a[tmp] ++;
    }
    
    // for(int i = 0; i < 26; i ++) cout << a[i] << endl;
    
    for(int i = 0; s[i] != '\0'; i ++)
    {
        int flag = s[i] - 'a';
        if(a[flag] == 1) 
        {
            printf("%c", s[i]);
           	return 0;
        }
    }
    puts("no"); 
    
    return 0;
}

2.8 字符串匹配

给定两个长度相同的字符串 a 和字符串 b。

如果在某个位置 i 上,满足字符串 a 上的字符 a[i] 和字符串 b 上的字符 b[i] 相同,那么这个位置上的字符就是匹配的。

如果两个字符串的匹配位置的数量与字符串总长度的比值大于或等于 k,则称两个字符串是匹配的。

现在请你判断给定的两个字符串是否匹配。

输入格式
第一行包含一个浮点数 k,第二行包含字符串 a,第三行包含字符串 b。

输入的字符串中不包含空格。

输出格式
如果两个字符串匹配,则输出 yes。

否则,输出 no。

数据范围
0≤k≤1,
字符串的长度不超过 100。

输入样例:
0.4
abcde
xbacd
输出样例:
no

#include 
#include 
using namespace std;

int main()
{
    string s1, s2;
    double k;
    cin >> k >> s1 >> s2;
    
    double tmp = 0;
    for(int i = 0; i < s1.size(); i ++)
    {
        if(s1[i] == s2[i]) tmp ++;
    }
    
    if(tmp / s1.size() >= k) cout << "yes" << endl;
    else cout << "no" << endl;
    return 0;
}

2.9 忽略大小写比较字符串大小

一般我们用 strcmp 可比较两个字符串的大小,比较方法为对两个字符串从前往后逐个字符相比较(按 ASCII 码值大小比较),直到出现不同的字符或遇到 \0 为止。

如果全部字符都相同,则认为相同;如果出现不相同的字符,则以第一个不相同的字符的比较结果为准。

但在有些时候,我们比较字符串的大小时,希望忽略字母的大小,例如 Hello 和 hello 在忽略字母大小写时是相等的。

请写一个程序,实现对两个字符串进行忽略字母大小写的大小比较。

输入格式
输入为两行,每行一个字符串,共两个字符串。注意字符串中可能包含空格。

数据保证每个字符串的长度都不超过 80。

输出格式
如果第一个字符串比第二个字符串小,输出一个字符 <。

如果第一个字符串比第二个字符串大,输出一个字符 >。

如果两个字符串相等,输出一个字符 =。

输入样例:

Hello
hello

输出样例:

=

#include 
#include 

using namespace std;
int main()
{
    //本来想用string类,可是strcmp不支持
    char s1[100], s2[100];
    //cin不支持空格输入
    fgets(s1, 100, stdin);
    fgets(s2, 100, stdin);
    
    //去掉换行空格,fgets不能自动过滤换行符,注意换行符在最后第二个位置上
    if(s1[strlen(s1) - 1] == '\n') s1[strlen(s1) - 1] = 0;
    if(s2[strlen(s2) - 1] == '\n') s2[strlen(s2) - 1] = 0;
    
    
    for(int i = 0; s1[i]; i ++)
    {
        if(s1[i] >= 'A' && s1[i] <= 'Z') s1[i] += 32;
    }
    
    for(int i = 0; s2[i]; i ++)
    {
        if(s2[i] >= 'A' && s2[i] <= 'Z') s2[i] += 32;
    }
    // puts(s1);
    int tmp = strcmp(s1, s2);
    if(tmp == 0) puts("=");
    else if(tmp > 0) puts(">");
    else if(tmp < 0) puts("<");
    
    return 0;
}

2.10 去掉多余的空格

输入一个字符串,字符串中可能包含多个连续的空格,请将多余的空格去掉,只留下一个空格。

输入格式
共一行,包含一个字符串。

输出格式
输出去掉多余空格后的字符串,占一行。

数据范围
输入字符串的长度不超过 200。
保证输入字符串的开头和结尾没有空格。

输入样例:
Hello world.This is c language.
输出样例:
Hello world.This is c language.

//此方法使用双指针标记的方法
#include 
#include 
using namespace std;

int main()
{
    char s1[201], s2[201];
    fgets(s1, 201, stdin);
    
    for(int i = 0, j = 0; s1[i] != '\0';)
    {
        if(s1[i] != ' ')
        {
            s2[j] = s1[i];
            j ++;
            i ++;
        }
        else if(s1[i] == ' ')
        {
            s2[j] = s1[i];
            while(s1[i] == ' ') i ++;
            j ++;
        }
        //最后一位填上结束位
        if(s1[i] == '\0') s2[j] = '\0';
    }
    cout << s2;
    
    return 0;
}
//方法二
#include 
#include 
using namespace std;

int main()
{
    string s;
    while(cin >> s) cout << s << " ";
    return 0;
}

2.11 信息加密

传输信息的过程中,为了保证信息的安全,我们需要对原信息进行加密处理,形成加密信息,从而使得信息内容不会被监听者窃取。

现在给定一个字符串,对其进行加密处理。

加密的规则如下:

字符串中的小写字母,a 加密为 b,b 加密为 c,…,y 加密为 z,z 加密为 a。
字符串中的大写字母,A 加密为 B,B 加密为 C,…,Y 加密为 Z,Z 加密为 A。
字符串中的其他字符,不作处理。
请你输出加密后的字符串。

输入格式
共一行,包含一个字符串。注意字符串中可能包含空格。

输出格式
输出加密后的字符串。

数据范围
输入字符串的长度不超过 100。

输入样例:
Hello! How are you!
输出样例:
Ifmmp! Ipx bsf zpv!

#include 
#include 
using namespace std;

int main()
{
    string s;
    getline(cin, s);
    
    char tmp;
    for(int i = 0; s[i] != '\0'; i ++)
    {
        if(s[i] >= 'a' && s[i] <= 'y') s[i] += 1;
        else if(s[i] == 'z') s[i] = 'a';
        else if(s[i] >= 'A' && s[i] <= 'Y') s[i] += 1;
        else if(s[i] == 'Z') s[i] = 'A';
    }
    puts(s.c_str());
    return 0;
}

改进写法

#include 
#include 
using namespace std;

int main()
{
    string s;
    getline(cin, s);
    
    char tmp;
    for(auto &c: s)
    {
        if(c >= 'a' && c <= 'z') c = 'a' + (c - 'a' + 1) % 26;
        if(c >= 'A' && c <= 'Z') c = 'A' + (c - 'A' + 1) % 26;
    }
    puts(s.c_str());
    return 0;
}

2.12 输出字符串

给定一个字符串 a,请你按照下面的要求输出字符串 b。

给定字符串 a 的第一个字符的 ASCII 值加第二个字符的 ASCII 值,得到 b 的第一个字符;

给定字符串 a 的第二个字符的 ASCII 值加第三个字符的 ASCII 值,得到 b 的第二个字符;

给定字符串 a 的倒数第二个字符的 ASCII 值加最后一个字符的 ASCII 值,得到 b 的倒数第二个字符;

给定字符串 a 的最后一个字符的 ASCII 值加第一个字符的 ASCII 值,得到 b 的最后一个字符。

输入格式
输入共一行,包含字符串 a。注意字符串中可能包含空格。

数据保证字符串内的字符的 ASCII 值均不超过 63。

输出格式
输出共一行,包含字符串 b。

数据范围
2≤a的长度≤100
输入样例:
1 2 3
输出样例:
QRRSd

#include 
#include 
using namespace std;

int main()
{
    string s1, s2;
    getline(cin, s1);
    int len = s1.size();
    
    for(int i = 0; s1[i] != '\0'; i ++)
    {
        //传统的写法
        // if(i + 1 <= len - 1) 
        // {
        //     s2 = s2 + (char)(s1[i] + s1[i + 1]);
        // }
        // else s2 += (s1[i] + s1[0]);
        
        //使用数学公式的写法
        s2 += (s1[i] + s1[(i + 1) % len]);
    }
    cout << s2 << endl;
    return 0;
}

2.13 单词替换

输入一个字符串,以回车结束(字符串长度不超过 100)。

该字符串由若干个单词组成,单词之间用一个空格隔开,所有单词区分大小写。

现需要将其中的某个单词替换成另一个单词,并输出替换之后的字符串。

输入格式
输入共 3 行。

第 1 行是包含多个单词的字符串 s;

第 2 行是待替换的单词 a(长度不超过 100);

第 3 行是 a 将被替换的单词 b(长度不超过 100)。

输出格式
共一行,输出将 s 中所有单词 a 替换成 b 之后的字符串。

输入样例:
You want someone to help you
You
I
输出样例:
I want someone to help you

//这是用字符串流来做的,字符串转化成字符串流的好处是空格会成为字符串参数内部分界的参数
//也可以用KMP算法来做
#include 
#include 
using namespace std;

int main()
{
    string s1, s2, s3;
    getline(cin, s1);
    cin >> s2 >> s3;
    
    stringstream ssin(s1);
    string tmp;
    while(ssin >> tmp)
    {
        if(tmp == s2) cout << s3 << " ";
        else cout << tmp << " ";
    }
    
    return 0;
}
//stringstream使用样例,相当于cin
//cin的方式
#include 
#include 
using namespace std;

int main()
{
    string s1;
    getline(cin, s1);
    
    stringstream ssin(s1);
    
    int a, b;
    string c;
    double d;
    
    ssin >> a >> b >> c >> d;
    
    cout << a << endl << b << endl << c << endl << d;
    
    return 0;
}
//sscanf()的方法
#include 
#include 
using namespace std;

int main()
{
    char s[100];
    fgets(s, 100, stdin);
    
    int a, b;
    char str[100];
    double c;
    
    sscanf(s, "%d%s%d%lf", &a, str, &b, &c);
    
    printf("%d\n%s\n%d\n%lf", a, str, b, c);
    
    return 0;
}

2.14 字符串中最长的连续出现的字符

求一个字符串中最长的连续出现的字符,输出该字符及其出现次数,字符串中无空白字符(空格、回车和 tab),如果这样的字符不止一个,则输出第一个。

输入格式
第一行输入整数 N,表示测试数据的组数。

每组数据占一行,包含一个不含空白字符的字符串,字符串长度不超过 200。

输出格式
共一行,输出最长的连续出现的字符及其出现次数,中间用空格隔开。

输入样例:
2
aaaaabbbbbcccccccdddddddddd
abcdefghigk
输出样例:
d 10
a 1

//双指针算法一
//指针i遍历字符串,指针j记录连续字符中的第一个坐标
#include 
using namespace std;

int main()
{
    int n; 
    cin >> n;
    
    while(n --)
    {
        string str;
        cin >> str;
        
        int len = 1;
        int max_len = 0;
        int flag = 0;
        for(int i = 0, j = 0; str[i]; i ++)
        {
            if(str[i + 1] == str[i])
            {
                len ++;
                continue;
            }
            else
            {
                if(len > max_len) 
                {
                    max_len = len;
                    len = 1;
                    // cout << "max_len:"<< max_len << endl;
                    // cout << "zuobiao:"<< j << endl;
                    flag = j;
                    j = i + 1;
                }
                else
                {
                    len = 1;
                    j = i + 1;    
                }
                
            }
        }
        
        cout << str[flag] << " " << max_len << endl;
        
    }
    
    return 0;
}
//更简单的双指针算法
//i指针连续字符串的第一个坐标,j指针从连续字符串第一个坐标开始遍历到连续字符串最后一个坐标
#include 
using namespace std;

int main()
{
    int n; 
    cin >> n;
    
    while(n --)
    {
        string str;
        cin >> str;
        
        int max_len = 0;
        char tmp;
        for(int i = 0; i < str.size(); i ++)
        {
            int j = i;
            while(j <= str.size() && str[j] == str[i]) j ++;
            if(j - i > max_len) max_len = j - i, tmp = str[i];
            i = j - 1;
        }
        
        cout << tmp << " " << max_len << endl;
    }
    
    return 0;
}

2.15 最长单词

一个以 . 结尾的简单英文句子,单词之间用空格分隔,没有缩写形式和其它特殊形式,求句子中的最长单词。

输入格式
输入这个简单英文句子,长度不超过 500。

输出格式
该句子中最长的单词。如果多于一个,则输出第一个。

输入样例:
I am a student of Peking University.
输出样例:
University

#include 
using namespace std;

int main()
{
    string str, res;
    
    while(cin >> str)
    {
        if(str.back() == '.') str.pop_back();
        if(str.size() > res.size()) res = str;
    }
    
    cout << res << endl;
    return 0;
}

2.16 倒排单词

编写程序,读入一行英文(只包含字母和空格,单词间以单个空格分隔),将所有单词的顺序倒排并输出,依然以单个空格分隔。

输入格式
输入为一个字符串(字符串长度至多为 100)。

输出格式
输出为按要求排序后的字符串。

输入样例:
I am a student
输出样例:
student a am I

#include 
#include 
using namespace std;

int main()
{
    string s[100];
    
    int i = 0;
    while(cin>> s[i]) i ++;
    
    for(int j = i - 1; j >= 0; j --)
    {
        cout << s[j] << " ";
    }
    return 0;
}

2.17 字符串移位包含问题

对于一个字符串来说,定义一次循环移位操作为:将字符串的第一个字符移动到末尾形成新的字符串。

给定两个字符串 s1 和 s2,要求判定其中一个字符串是否是另一字符串通过若干次循环移位后的新字符串的子串。

例如 CDAA 是由 AABCD 两次移位后产生的新串 BCDAA 的子串,而 ABCD 与 ACBD 则不能通过多次移位来得到其中一个字符串是新串的子串。

输入格式
共一行,包含两个字符串,中间由单个空格隔开。

字符串只包含字母和数字,长度不超过 30。

输出格式
如果一个字符串是另一字符串通过若干次循环移位产生的新串的子串,则输出 true,否则输出 false。

输入样例:
AABCD CDAA
输出样例:
true

//这是暴力做法,思路简单先移位,然后
#include 
#include 
using namespace std;

int main()
{
    string s1, s2;
    cin >> s1 >> s2;
    if(s1.size() < s2.size()) swap(s1, s2);
    
    string tmp1, tmp2;
    for(int i = 0; i < s1.size(); i ++)
    {
        tmp1 = s1.substr(i, s1.size() - i) + s1.substr(0, i);
        //检查s2是不是s1的子集
        for(int k = 0; k < tmp1.size(); k ++)
        {
            for(int j = k + 1; j < tmp1.size(); j ++)
            {
                tmp2 = tmp1.substr(k, j - k + 1);
                if(tmp2 == s2)
                {
                    cout << "true" << endl;
                    return 0;
                }
                else continue;
            }
        }
    }
    cout << "false" << endl;
    return 0;
}

2.18 字符串乘方

给定两个字符串 a 和 b,我们定义 a×b 为他们的连接。

例如,如果 a=abc 而 b=def, 则 a×b=abcdef。

如果我们将连接考虑成乘法,一个非负整数的乘方将用一种通常的方式定义:a0=``(空字符串),a(n+1)=a×(an)。

输入格式
输入包含多组测试样例,每组测试样例占一行。

每组样例包含一个字符串 s,s 的长度不超过 100。

最后的测试样例后面将是一个点号作为一行。

输出格式
对于每一个 s,你需要输出最大的 n,使得存在一个字符串 a,让 s=an。

输入样例:
abcd
aaaa
ababab
.
输出样例:
1
4
3

#include 
#include 
using namespace std;

int main()
{
    string str;
    
    while(cin >> str, str != ".")
    {
        int len = str.size();
        //这里有个技巧,从最大的递减,第一个符号要求的n就是最大的n
        for(int n = len; n; n--)
        {
            if(len % n == 0) 
            {
                int m = len / n;
                string res;
                string par = str.substr(0, m);
                for(int j = 0; j < n; j ++)
                {
                    res += par;
                }
                if(res == str)
                {
                    cout << n << endl;
                    break;
                }
            }
        }
        
    }
    return 0;
}

2.19 字符串最大跨距

有三个字符串 S,S1,S2,其中,S 长度不超过 300,S1 和 S2 的长度不超过 10。

现在,我们想要检测 S1 和 S2 是否同时在 S 中出现,且 S1 位于 S2 的左边,并在 S 中互不交叉(即,S1 的右边界点在 S2 的左边界点的左侧)。

计算满足上述条件的最大跨距(即,最大间隔距离:最右边的 S2 的起始点与最左边的 S1 的终止点之间的字符数目)。

如果没有满足条件的 S1,S2 存在,则输出 −1。

例如,S= abcd123ab888efghij45ef67kl, S1= ab, S2= ef,其中,S1 在 S 中出现了 2 次,S2 也在 S 中出现了 2 次,最大跨距为:18。

输入格式
输入共一行,包含三个字符串 S,S1,S2,字符串之间用逗号隔开。

数据保证三个字符串中不含空格和逗号。

输出格式
输出一个整数,表示最大跨距。

如果没有满足条件的 S1 和 S2 存在,则输出 −1。

输入样例:
abcd123ab888efghij45ef67kl,ab,ef
输出样例:
18

#include 
#include 
using namespace std;

int main()
{
    string s, s1, s2;
    char c;
    while(cin >> c, c != ',') s += c;
    while(cin >> c, c != ',') s1 += c;
    while(cin >> c) s2 += c;
    
    //l为字符串s的左游标
    int l = 0;
    bool flag1 = false;
    while(l + s1.size() <= s.size())
    {
    	//i为字符串s1的游标
        for(int i = 0; i < s1.size(); i ++)
        {
            if(s1[i] != s[l + i])
            {
                if(l + i + 1 == s.size())
                {
                    puts("-1");
                    return 0;
                }
                else break;
            }
            else
            {
                if(i + 1 == s1.size())
                {
                    flag1 = true;
                    break;      
                }
                continue;
            }
        }
        if(flag1) break;
        l ++;
    }

	//r为字符串s的右游标
    int r = s.size() - s2.size();
    bool flag2 = false;
    while(r >= 0)
    {
    	//i为字符串s2上的游标
        for(int i = 0; i < s2.size(); i ++)
        {
            if(s2[i] != s[r + i])
            {
                if(r + i  + 1 == s2.size())
                {
                    puts("-1");
                    return 0;
                }
                else break;
            }
            else
            {
                if(i + 1 == s2.size())
                {
                    flag2 = true;
                    break;
                }
                continue;
            }
        }
        if(flag2) break;
        r --;
    }
    
    if(r <= l)
    {
        puts("-1");
        return 0;
    }
    
    cout << r - (l + s1.size()) << endl;
    return 0;
}

2.20 最长公共字符串后缀

给出若干个字符串,输出这些字符串的最长公共后缀。

输入格式
由若干组输入组成。

每组输入的第一行是一个整数 N。

N 为 0 时表示输入结束,否则后面会继续有 N 行输入,每行是一个字符串(字符串内不含空白符)。

每个字符串的长度不超过 200。

输出格式
共一行,为 N 个字符串的最长公共后缀(可能为空)。

数据范围
1≤N≤200
输入样例:
3
baba
aba
cba
2
aa
cc
2
aa
a
0
输出样例:
ba

a

#include 
#include 
using namespace std;

const int N = 200;
string s[N];

int main()
{
    int n;
    string s[N];
    
    
    while(cin >> n, n)
    {
        int min_len = 1000;
        for(int i = 0; i < n; i ++)
        {
            cin >> s[i];
            if(min_len > s[i].size()) min_len = s[i].size();
        }
        
        
        while(min_len)
        {
            bool is_success = true;
            for(int i = 1; i < n; i ++)
            {
                bool is_same = true;
                for(int j = 1; j <= min_len; j ++)
                {
                    if(s[0][s[0].size() - j] != s[i][s[i].size() - j])
                    {
                        is_same = false;
                        break;
                    }
                }
                if(!is_same)
                {
                    is_success = false;
                    break;
                }
            }
            if(is_success) break;
            min_len --;
        }
        
         cout << s[0].substr(s[0].size() - min_len) << endl;
    }
   
    return 0;
}

你可能感兴趣的:(C++语法基础练习题,c/c++,c语言,贪心算法,算法)