判断子序列
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"
是"abcde"
的一个子序列,而"aec"
不是)。
进阶:
如果有大量输入的 S,称作 S1, S2, … , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?
方法一
用双指针非常容易想到
1 2 3 4 5 6 7 8 9 10 11
| class Solution { public: bool isSubsequence(string s, string t) { int i=0,j=0; while(i<s.size()&&j<t.size()){ if(s[i]==t[j]) i++; j++; } return i>=s.size()?true:false; } };
|
方法二
动态规划
f[i][j]
表示在字符串t
中,从位置i
开始,j
第一次出现的位置。
因为字符串只包括小写字母,所以j
的范围是[0,25]
.
状态转移方程
1 2 3 4
| f[i][j]={ i, t[i]-'a'==j f[i+1][j], otherwise //所以i需要倒序遍历 }
|
初始化
1
| for(int i=0;i<26;i++) f[len_t][i]=len_t;
|
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class Solution { public: bool isSubsequence(string s, string t) { int len_s=s.size(); int len_t=t.size(); vector<vector<int>>f(len_t+1,vector<int>(26,0)); for(int i=0;i<26;i++) f[len_t][i]=len_t; for(int i=len_t-1;i>=0;i--){ for(int j=0;j<26;j++){ if(t[i]=='a'+j) f[i][j]=i; else f[i][j]=f[i+1][j]; } } int add=0; for(int i=0;i<len_s;i++){ if(f[add][s[i]-'a']==len_t) return false; else add=f[add][s[i]-'a']+1; } return true; } };
|