题目大意:有n个DNA序列,构造一个新的序列,使得这n个DNA序列都是它的子序列,然后输出最小长度。
题解:第一次接触IDA*算法,感觉~~好暴力!!思路:维护一个数组pos[i],表示第i个串该匹配第pos[i]个元素。一共有四种可能,A,C,G,T,依次枚举,如果说A和n个串中的第j个串匹配,就直接就pos[j]++就行了,然后进入下一层,如果说最终没有成功构造,还有进行回溯,所以每一层我们都要维护一个数组来记录pos的值方便回溯。
具体实现和注释都在code中了,应该不难理解.
code:
#include<bits/stdc++.h>
using namespace std;
const int N=20;
int len[N];
string s[N];
int n;
string st="AGCT";
int pos[N];//表示第i个字符串匹配该第pos[i]个位置
int get(){//用来表示当前最少要走多少部步
int ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,len[i]-pos[i]);
return ans;
}
bool dfs(int step,int depth){
if(step+get()>depth) return 0;//长度不够
if(!get()) return 1;//全部匹配成功
int temp[20];//回溯的时候会用到
for(int i=1;i<=n;i++) temp[i]=pos[i];
for(int i=0;i<4;i++){//A C G T,依次枚举匹配
bool flag=0;//用来记录第j个string,pos[j]处的字符串是否匹配成功.
for(int j=1;j<=n;j++){
if(s[j][pos[j]]==st[i]){
flag=1;
pos[j]++;
}
}
if(flag){//flag=1,说明至少有一个串和st[i]匹配.
if(dfs(step+1,depth)) return 1;
for(int i=1;i<=n;i++) pos[i]=temp[i];
}
}
return 0;
}
int main(){
ios::sync_with_stdio(0);
int t;
cin>>t;
while(t--){
memset(len,0,sizeof len);
memset(pos,0,sizeof pos);
cin>>n;
string c;
int maxn=0;
for(int i=1;i<=n;i++){
cin>>s[i];
len[i]=s[i].size();
maxn=max(maxn,len[i]);
}
while(1){
if(dfs(0,maxn)) break;
maxn++;
}
cout<<maxn<<endl;
}
return 0;
}