leetcode_字节跳动_挑战字符串_字符串的排列

  字符串的排列
 

给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。

换句话说,第一个字符串的排列之一是第二个字符串的子串。

示例1:

输入: s1 = "ab" s2 = "eidbaooo"
输出: True
解释: s2 包含 s1 的排列之一 ("ba").

 

示例2:

输入: s1= "ab" s2 = "eidboaoo"
输出: False

 

注意:

  1. 输入的字符串只包含小写字母
  2. 两个字符串的长度都在 [1, 10,000] 之间

     

解题思路:
解决这个问题前可以先回顾下无排列的子串匹配问题,我们当时使用的是实现了DFA状态转移图,当匹配到不同字符时来到不同的状态,知道最终完全匹配。

(图后补,下次一定)

而对于有排列的子串问题,我们一样可以构建一个DFA图来实现它,在这时候相比于无排列子串匹配问题,子串的字符顺序就不重要了,思路如下:

(图后补,下次一定)

逐个判断长字符串字符:
(1)不是子串字符,跳过

(2)是子串字符且没多余重复,记录当前匹配到的长度

(3)是子串字符但是已经多余了,比如子串“adc”,串“dcda“,第二个d是超出了子串d个数的,从第二个d这个位置往前重新匹配到dc。

(4)若匹配到的个数已经达到子串长度,完成。

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        
        int len_s1 = s1.length();
        int len_s2 = s2.length();
        if(len_s1>len_s2) return false;
        if(len_s1==0) return true;
        if(len_s1==1){
            for(int i=0;i<len_s2;i++){
                if(s1[0]==s2[i]) return true;
            }
            return false;
        }
        
        int size[26];//子串字符统计
        int size_tmp[26];//临时子串已用字符统计
        memset(size,0,sizeof(int)*26);
        memset(size_tmp,0,sizeof(int)*26);
            
        map<char,int> mp;
        for(int i=0;i<len_s1;i++){
            mp.insert(pair<char,int>(s1[i],i));//map容器储存,方便查找
            size[s1[i]-'a']++;//记录个数
        }
        
        int len=0;
        
        for(int i=0;i<len_s2;i++){
            //不是子串字符重置跳过
            if(mp.find(s2[i])==mp.end()){
                len=0;
                memset(size_tmp,0,sizeof(int)*26);
                continue;
            }
            
            //是子串字符,判断是否多余出现
            //  cout<<s1[j]<<"--"<<s2[i]<<endl;
                if(size_tmp[s2[i]-'a']<size[s2[i]-'a']){//存在且还有可用空间
                    len++;
                    size_tmp[s2[i]-'a']++; 
                }
                else if(size_tmp[s2[i]-'a']==size[s2[i]-'a']){//没有可用空间了,说明重复了子串一个字符
                   /**当前字符是s1中已经访问过的字符,则往前重新访问记录到无法继续访问**/
                   len=0;
                   memset(size_tmp,0,sizeof(int)*26);
                   int z;
                   for(int z=i;z>=0;z--){
                       if(mp.find(s2[z])==mp.end()) break;//不是子串内容退出
                          
                       if(size_tmp[s2[z]-'a']<size[s2[z]-'a']){//存在且有容量
                            len++;
                            size_tmp[s2[z]-'a']++;
                       }
                       else if(size_tmp[s2[z]-'a']==size[s2[z]-'a']) break; //没有容量了
                   }
                }
            if(len==len_s1) return true;
        }
        return false;
    }
};

此处可以不用map容器,只是一开始查找想到了map,后来规定状态才想到了数组。

posted @ 2020-07-12 00:00  dragonsbug  阅读(237)  评论(0编辑  收藏  举报