题意:给定两个字符串s和t,问只通过删除字符的方法将s变为t有多少种方法
解法:本题是典型的动态规划,给出两种解法(第一种是我自己的比较烦琐,第二种是网上的思路比较清楚)。就算是思路较烦琐,也是我想的,我觉得这是我独立做出了的第一道dp题,开心~。
解法一:用ans[i][j]表示以s[i]结尾能到t[j]有多少种方法。则对于ans[i][0],只要把s里面的所有等于t[0]的下标设置成1即可。对于i>=1的情况,先取出s里等于t[j-1],t[j]的所有下标组合pre,cur,然后对于每个cur[i],遍历pre,如果ans[j][i-1]!=0的话,则ans[cur[j]][i]+=ans[pre[k]][i-1],返回ans里第二个下标为t.length()-1的数字之和即可。
代码如下:
class Solution {
public:
int numDistinct(string s, string t) {
int i,j,k,ls=s.length(),lt=t.length(),res=0;
map<int,vector<int>> sletter;
vector<int> pre,cur;
vector<vector<int>> ans;
for(i=0;i<lt;i++) pre.push_back(0);
for(i=0;i<ls;i++) ans.push_back(pre);
for(i=0;i<ls;i++) sletter[s[i]-'a'].push_back(i);
for(i=0;i<ls;i++) if(s[i]==t[0]) ans[i][0]=1;
for(i=1;i<lt;i++)
{
pre=sletter[t[i-1]-'a'];
cur=sletter[t[i]-'a'];
for(j=0;j<cur.size();j++)
{
for(k=0;k<pre.size();k++)
{
if(pre[k]<cur[j]&&ans[pre[k]][i-1]!=0) ans[cur[j]][i]+=ans[pre[k]][i-1];
}
}
}
for(i=0;i<ls;i++) res+=ans[i][lt-1];
return res;
}
};
解法二:(从网上抄的),这个方法思路很清晰,由于只能通过删除字符的方法,所以分两种情况。设ans[i][j]是s[i]变化到t[j]的方法数目。若s[i]!=t[j],则ans[i][j]=ans[i-1][j](因为只能丢到ans[i]字符),否则既可以丢也可以不丢ans[i][j]=ans[i-1][j]+ans[i-1][j-1]。不上代码了,比较简单