PAT字符串专题复习

PAT字符串专题复习

  • 最长连续公共子串求解

    • 用最长不连续公共子序列的变形来做

      • 思路:

        ①令dp[i] [j]表示字符串a中结尾为i和字符串b中结尾为j的前一段字符子串中连续公共子串的长度。例如afbc和abcde中,dp[4] [3] = 2, dp[4] [4] = 0.

        ②状态转移方程:

        int maxlen = 0; //记录最长连续子串长度,注意不能最后直接输出dp[i][j].
        if(a[i] == b[j]){
            dp[i][j] = dp[i-1][j-1] + 1;
            maxlen = max(maxlen, dp[i][j]);
        }else{
            dp[i][j] = 0;
        }
        cout << maxlen;
        
  • 字符串排序

    • PAT A 1047 vector+char数组

      • 当题目所给数据过大时,例如40000级别;使用string类型进行排序比使用char数组类型进行排序将慢的多。如果遇到string类型超时的时候,不妨换做char数组类型试一下。

      • 此外,cmp函数对char数组排序需要熟练掌握。

        char s[1010][5];
        bool cmp(int a, int b){
            return strcmp(s[a]), s[b]) < 0; //升序排序
        }
        
      • #include<bits/stdc++.h>
        using namespace std; 
        char name[40005][5];
        vector<int> ans[40005];
        //字符数组排序 
        bool cmp(int a, int b){
        	return strcmp(name[a], name[b]) < 0;
        }
        int main(){
        	int n, k, num, id;
        	cin >> n >> k;
        	for(int i = 0; i < n; i++){
        		cin >> name[i] >> num;
        		while(num--){
        			cin >> id;
        			ans[id].push_back(i);
        		}
        	}
        	for(int i = 1; i <= k; i++){
        		printf("%d %d\n", i, ans[i].size());
        		sort(ans[i].begin(), ans[i].end(), cmp);
        		for(int j = 0; j < ans[i].size(); j++){
        			printf("%s\n", name[ans[i][j]]);
        		}
        	}
        	return 0;
        }
        
  • 包含空格的字符串分割处理

    • 题目描述:PAT A 1071

      • 思路:

        ①首先使用getline(cin, str);读入一行包含空格的字符串。

        ②然后,使用isalnum函数判断是否是符合条件的字母和数字;如果是,就让t加上这个字符;如果不是则表明是分隔符,同时注意,最后一个单词右端不会出现分隔符,需要进行特判。

        ③另外,在使用map时,要先判断字符串是否为空,因为空的字符串也可以存入到map中。

        string s = "";
        mp[s] = 1;
        printf("%d", mp[s]); //输出 “1”
        
      • 代码实现

        #include<bits/stdc++.h>
        using namespace std; 
        int main(){
        	string s, t;
        	getline(cin, s);
        	map<string, int> m;
        	for(int i = 0; i < s.length(); i++){
        		if(isalnum(s[i])){
        			s[i] = tolower(s[i]);
        			t += s[i];
        		}
        		//当遇到不是数字字母即为分隔符或者到整行字符串末尾时 
        		if(!isalnum(s[i]) || i == s.length() - 1){
        			//只有当t不为空时,才能进行map的相关操作;不然,空字符串也可以存储下来。 
        			if(t.length() != 0)m[t]++;
        			t = "";
        		}
        	}
        	int maxn = 0;
        	for(auto it = m.begin(); it != m.end(); it++){
        		if(it->second > maxn){
        			t = it->first;
        			maxn = it->second;
        		}
        	}
        	cout << t << " " << maxn;
        	return 0; 
        }
        
  • 字符串函数

    • isalnum(int c)函数,检查所传的字符是否是字母和数字。

      //参数c是要检查的字符,函数返回bool类型值
      char c = 'a';
      if(isalnum(c)){
          printf("'a'是字母");
      }
      int a = 0;
      if(isalnum(a)){
          printf("a是数字");
      }
      
    • 将字符转为大写字符或小写字符函数。tolower和toupper函数。【注意:只能对单个字符进行转换】

      string s;
      for(int i = 0; i < s.length(); i++){
          s[i] = tolower(s[i]); //转为小写字母
          s[i] = toupper(s[i]);//转为大写字母
      }
      
    • strcmp函数使用

      ①strcmp函数使用。返回值 < 0,表示str1 小于 str2;返回值 = 0, 表示相等;返回值 > 0,表示str1大于str2.

      ②在cmp函数中比较和与类似字符串“in”判断是否相等。

    //strcmp函数在cmp中比较字符数组
    struct node{
    char s[30];
    int time;
    }
    bool cmp(node a, node b){
    if(strcmp(a.s, b.s) != 0){//表示两个字符数组不相等
    return strcmp(a.s, b.s) < 0; //表示升序排序
    }
    else return a.time < b.time;
    }

    //strcmp函数比较一个字符串和一个字符数组变量
    char s[10];
    if(strcmp(s, “in”) == 0){
    ……
    }

    
    - map<string, int> 使用
    
    ②map<string, int> 中可以存放字符数组类型。放入后会从字符数组类型变为string类型。
    
    ```c++
    char s[100];
    cin >> s;
    mp[s] = 2;//char数组类型可以直接存入到map的string类型中,存入后char数组将变成string类型 
    auto it = mp.begin();
    printf("%s %d", (it->first).c_str(), it->second);
    
  • 字符串处理模拟题

    • A 1082 : 用中文表示数据读法

      • 思路:

        ①整体思路是将数字按字符串方式处理,并设置下标left和right来处理数字的每一个节(个节、万节、亿节)的输出,即令left指向当前需要输出的位,而right指向与left同节的个位。

        ②在需要输出的某个节中,需要解决的问题是如何处理额外发音的零。处理方法如下:设置bool型变量flag表示当前是否存在累积的零。当输出left指向的位之前,先判断该位是否为0;如果为0,则令flag为true,表示存在累积的0;如果非0,则根据flag的值来判断是否需要输出额外的零。在这之后,就可以输出该位本身以及该位对应的位号(十、百、千)。而当整一小节处理完毕之后,再输出万或者亿。

      • 代码实现

        //太过复杂,看书上题解
        #include<bits/stdc++.h>
        using namespace std;
        char num[10][5] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
        char wei[5][5] = {"Shi", "Bai", "Qian", "Wan", "Yi"};
        int main(){
        	char str[15];
        	cin >> str;
        	int len = strlen(str);
        	int left = 0, right = len - 1; //left与right分别指向字符串首尾元素
        	if(str[0] == '-'){
        		printf("Fu");
        		left++;
        	} 
        	while(left + 4 <= right){
        		right -= 4; //让left与right到同一节 
        	}
        	while(left < len){//每次循环处理数字的一节 
        		bool flag = false; //flag==false表示没有积累的0要输出
        		bool isPrint = false; //isPrint==false表示该节没有输出过其中的位
        		while(left <= right){//从左至右处理数字中某节的每一位 
        			if(left > 0 && str[left] == '0'){//如果当前位不是首尾,且值为0 
        				flag = true;
        			}
        			else{
        				if(flag){//等到遇到不是0的一位之后,输出积累的0 
        					printf(" ling");
        					flag = false;
        				}
        				//只要不是首位, 后面的每一位前都要输出空格
        				if(left > 0)printf(" ");
        				printf("%s", num[str[left] - '0']);//输出当前数字
        				isPrint = true;//该节至少有一位输出,所以这一节不能省略
        				if(left != right){//某一节中除了个位,其他位需要输出十百千 
        					printf(" %s", wei[right - left - 1]);
        				} 
        			}
        			left++;//left往右移动1位 
        		} 
        		if(isPrint == true && right!= len - 1){//只要不是个位,就输出万或亿 
        			printf(" %s", wei[(len - 1 - right) / 4 + 2]); 
        		} 
        		right += 4; //right右移4位,输出下一节 
        	}
        	return 0;
        } 
        
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦想总比行动多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值