题目描述
题解
f[i][j]表示状态为j,最后一个子串是i的最短的字符串的长度。
不过这里有一个问题,就是用来转移的所有字符串不能存在包含关系。也就是说,字符串只能存在部分相交或相离。这样的话才能保证每一次都是部分接在了前一个的最后一个字符串后面,从而保证了dp的无后效性。部分包含的循序是不要紧的,因为总会有从正确的顺序转移过来的。
字典序的话就记一下转移的前驱然后暴力还原判断辣,中间转移和最后统计答案的时候都要考虑字典序的影响。其实写起来不算很简单。
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
int n,tot,ans,ansi,inf;
struct hp
{
char s[100];
int len,exlen,prei,prej;
}s[20],str[20],f[20][5000];
char s1[1000],s2[1000]; int cnt1,cnt2;
bool vis[20][5000];
struct sit{
int i,j;};
queue <sit> q;
int cmp(hp a,hp b)
{
return a.len>b.len;
}
bool included(int a,int b)
{
for (int i=0;i<s[a].len;++i)
if (s[a].s[i]==s[b].s[0])
{
bool flag=true;
for (int j=0;j<s[b].len;++j)
if (s[a].s[i+j]!=s[b].s[j])
{
flag=false;
break;
}
if (flag) return true;
}
return false;
}
int connext(int a,int b)
{