字符串问题

字符串问题

字符串问题是数据结构与算法考查的重点:主要涉及滑动窗口,动态规划等问题的使用!

  • 字符串1:最长回文串 (简单逻辑)

    int longestPalindrome(string s) {
          map<char,int>m;
          for(auto i:s){
              m[i]++;
          }
          int res=0;
          for(auto it:m){
              int v=it.second;
              res+=v/2*2;  //记录偶数个数
              if(res%2==0&&v%2==1) ++res;  //存在奇数+1
          }
          return res;
      }
  • 字符串2:最长回文子串 (动态规划)

    思路逻辑五步走:(填表运算)
    状态:dp[i][j]表示子串,S[i,j]是否为回文子串?
    转移方程:dp[i][j]=(s[i]==s[j])&&dp[i+1][j-1]
    边界条件:j-1-(i+1)+1<2 j-i<3
    初始值:dp[i][i]=true; (逐层计算上三角)
    输出:记录为true时,最大的长度与初始位置。

    #include<iostream>
    #include<string>
    #include<map>
    #include<vector>
    #include<algorithm>
    using namespace std;
    /*字符串  最长循环子串  动态规划*/
    string longestPalindrome(string s) {
      if(s.size()<2) return s;
      int len=s.size();
      int begin_index=0;
      int maxlen=0;
      vector<vector<bool>>dp(len,vector<bool>(len,false));
      for(int i=0;i<len;i++){   /*初始化*/
          dp[i][i]=true;
      }
      for(int j=1;j<len;j++){   /*从左到右依次遍历*/
          for(int i=0;i<len;i++){
              if(s[i]!=s[j]) dp[i][j]=false;
              else{
                  if(j-i<3){  /*边界条件*/
                      dp[i][j]=true;
                  }
                  else{
                      dp[i][j]=dp[i+1][j-1];  /*dp[i+1][j-1]在dp[i][j]之前获得*/
                  }
              }
              if(dp[i][j]&&j-i+1>maxlen){    /*结果输出*/
                  maxlen=j-i+1;
                  begin_index=i;
              }
          }
      }
      return s.substr(begin_index,maxlen);
    }
    int main(){
      string s="abababab";
      string res=longestPalindrome(s);
      cout<<res<<endl;
      return 0;
    }
  • 字符串3:最长不重复子串(滑动窗口)

    滑动窗口: l,r,res的选取与移动(左窗口,右窗口,输出接口+判断条件)

    #include<iostream>
    #include<map>
    #include<string>
    using namespace std;
    /*字符串:最长不重复的子串  滑动窗口*/
    string getsubstr(string str){
      if(str.size()<=1) return str;
      map<char,int>m;
      int l=0,r=0;
      string res;
      int maxLen = 0;
      while(r<str.size()){     //遍历至结束
          char h = str[r];
          m[h]++;
          r++;                 //提前加1
          while(m[h] > 1){     //保证窗口元素一直无重复元素
              m[str[l++]]--;
          }
          if(maxLen < r - l){
              maxLen = r - l;
              res = str.substr(l, r - l);
              //cout<<l<<" "<<r<<endl;
              //cout<<res<<endl;
          }
      }
      return res;
    }
    int main(){
      string str="abcbbabcd";
      string res=getsubstr(str);
      cout<<res<<endl;
      return 0;
    }
  • 字符串4:重复的DNA序列 (常规map的应用)

    vector<string> findRepeatedDnaSequences(string s) {
          vector<string>res;
          int k=10;
          map<string,int>m;
          if(s.size()<=k) return res;
          for(int i=0;i<=s.size()-k;i++){
              m[s.substr(i,k)]++;
          }
          for(auto j:m){
              if(j.second>1) res.push_back(j.first);
          }
          return res;
    }
  • 字符串5:最小覆盖子串 (滑动窗口)

    注意int (s.size()) != s.size()

    map<char,int>mt,ms;
    
      bool check(){
          for(auto &i:mt){
              if(ms[i.first]<i.second) return false;
          }
          return true;
      }
    
      string minWindow(string s, string t) {
          string res;
          if(s.size()<t.size()) return res;
    
          for(auto &i:t){
              mt[i]++;
          }
    
          int l=0,r=-1,lenmax=INT_MAX;
          int begin_index=-1;
         while (r < int(s.size())){ //注意转化为int
              if(mt.find(s[++r])!=mt.end()) ms[s[r]]++; /*第一个包含所有t的窗口*/
              while(check()&&l<=r){  /*剪枝操作*/
                  if(r-l+1<lenmax){
                      lenmax=r-l+1;
                      begin_index=l;
                  }
                  if(mt.find(s[l])!=mt.end()) ms[s[l]]--;
                  ++l;
              }
          } 
          return begin_index==-1?res:s.substr(begin_index,lenmax);
  • 字符串6:字母异位词 (map的灵活应用)

    vector<vector<string>> groupAnagrams(vector<string>& strs) {
          vector<vector<string>>res;
          if(strs.size()<1) return res;
          map<string,vector<string>>m;
          for(auto i:strs){
              string s=i;
              sort(s.begin(),s.end());
              m[s].push_back(i);
          }
          for(auto j:m){
              res.push_back(j.second);
          }
          return res;
      }
  • 字符串7:不同的循环子字符串

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务