首页 > 其他 > 详细

392判断子序列

时间:2019-12-01 12:46:59      阅读:67      评论:0      收藏:0      [点我收藏+]

判断子序列

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

示例 1:
s = "abc", t = "ahbgdc"

返回 true.

示例 2:
s = "axc", t = "ahbgdc"

返回 false.

后续挑战 :

如果有大量输入的 S,称作S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

1 思路:依次取s中元素在t中查找
2 字符串s是字符串t的子序列,那么字符串s中的所有字符都会按照顺序出现在字符串t中。
3 对子串进行遍历,同时也对母串进行遍历,一旦两个字符串匹配之后,就选择从母串匹配后的下一个位置继续下面的匹配,
4 而不在从头开始匹配。空串也是母串的子串。
 1 解法1:
 2 //40 ms    16.8 MB    
 3 class Solution {
 4 public:
 5     bool isSubsequence(string s, string t) {
 6         //暴力的解法
 7         //为空串时 也是子串
 8         int cnt=0;
 9         bool flag;
10         for(int i=0;i<s.size();i++){
11             flag=false;//标记不能找到
12             for(int j=cnt;j<t.size();j++){
13                 if(s[i]==t[j]){
14                     flag=true;//标记能找到
15                     cnt=j+1;//从匹配的字符后面下一个开始 继续查找,当长度10亿时,超时
16                     break;
17                 }
18             }
19             if(flag==false){//没有匹配的单词,可以返回false 了
20                 return false;
21             }
22         }
23          return true;
24     }
25 };
 1 解法2:
 2 //48ms 17 MB
 3 class Solution {
 4 public:
 5     bool isSubsequence(string s, string t) {
 6         //双指针解法:
 7         int i,j;
 8         for(i=0,j=0;i<s.size()&&j<t.size();j++){
 9             if(s[i]==t[j]){
10                 i++;
11             }
12         }
13         return i==s.size();
14 
15     }

16 };

 

 1  1 思路:
 2  2 
 3  3 状态:dp[i][j]为s的从头开始到i的子字符串是否为t从头开始到j的子字符串的子序列
 4  4 
 5  5 状态转移公式:
 6  6 
 7  7 当char[i]==char[j]时,则字符i一定是j的子序列,如果0~i-1子字符串是0~j-1子字符串的子序列,则dp[i][j]=true,所以dp[i][j] = dp[i-1][j-1];
 8  8 当char[i]!=char[j]时,即判断当前0~i子字符串是否是0~j-1的子字符串的子序列,即dp[i][j] = dp[i][j - 1]。如ab,eabc,虽然s的最后一个字符和t中最后一个字符不相等,但是因为ab是eab的子序列,所以ab也是eabc的子序列
 9  9 初始化:空字符串一定是t的子字符串的子序列,所以dp[0][j]=true;任意字符串非空 都不是 空字符的字符串 dp[i>0][0]=false;
10 10 
11 11 结果:返回dp[sLen][tLen]
12 
13 解法3:1508 ms    78.3 MB
14 
15 class Solution {
16 public:
17     bool isSubsequence(string s, string t) {
18         //使用动态规划做:虽然很慢,但是需要练习一下
19         int lens=s.size(),lent=t.size();
20         if(lens==0) return true;
21         if(lens>lent) return false;
22       //  bool dp[101][600010];//数组越界初始化500001,遇到551742长度
23         bool dp[lens+1][lent+1];//可以使用 字符串长度进行初始化
24         for(int i=1;i<=lens;i++) dp[i][0]=false;//任意字符串s都不是空串的字符串
25         for(int j=0;j<=lent;j++) dp[0][j]=true;//任意空串 s  都是 字符串t的 子串
26         for(int i=1;i<=lens;i++){
27             for(int j=1;j<=lent;j++){
28                 if(s[i-1]==t[j-1]) dp[i][j]=dp[i-1][j-1];
29                 else dp[i][j]=dp[i][j-1];
30             }
31         }
32         return dp[lens][lent];
33 
34     }
35 };

 

 1 解法6:112 ms    34 MB
 2 class Solution {
 3 public:
 4     bool isSubsequence(string s, string t) {
 5         unordered_map<char,vector<int>> mp;
 6         int len,left,right;
 7         for(int i=0;i<t.size();i++){
 8             mp[t[i]].push_back(i);//对每个t中的字符 存储它所在的位置,由小到大
 9         }
10         int curloc=0;//当前位置为0
11         for(char ch:s){//对字符串s中的每个字符 进行遍历
12             len=mp[ch].size();//取出t中相对应字母所在的 所有位置,进行查找
13             if(len==0) return false;//为空,字符串t中没有出现相应的字母 
14             if(curloc>mp[ch][len-1]) return false;//如果当前位置超过t中相对应字符的最后一个位置,无法匹配
15             left=0,right=len-1;
16             while(left<right){//执行完这个二分查找之后,left==right 
17                 int mid=(left+right)/2;
18                 if(mp[ch][mid]>curloc) right=mid;
19                 else left=mid+1;
20             }
21             curloc=mp[ch][left];
22         }
23         return true;
24     }
25 };

 

 

392判断子序列

原文:https://www.cnblogs.com/NirobertEinteson/p/11965427.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!