4032: [HEOI2015]最短不公共子串
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 428 Solved: 207
[ Submit][ Status][ Discuss]
Description
在虐各种最长公共子串、子序列的题虐的不耐烦了之后,你决定反其道而行之。
一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是。
一个串的“子序列”指的是它的可以不连续的一段,例如bde是abcdef的子串,但bdd不是。
下面,给两个小写字母串A,B,请你计算:
(1) A的一个最短的子串,它不是B的子串
(2) A的一个最短的子串,它不是B的子序列
(3) A的一个最短的子序列,它不是B的子串
(4) A的一个最短的子序列,它不是B的子序列
Input
有两行,每行一个小写字母组成的字符串,分别代表A和B。
Output
输出4行,每行一个整数,表示以上4个问题的答案的长度。如果没有符合要求的答案,输出-1.
Sample Input
aabbcc
abcabc
abcabc
Sample Output
2
4
2
4
4
2
4
HINT
对于100%的数据,A和B的长度都不超过2000
Source
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 2002;
const int N = 26;
const int INF = ~0U>>1;
struct Node{
int x,y,z; Node(){}
Node(int x,int y,int z): x(x),y(y),z(z){}
};
int na,nb,rt,cnt,f[maxn][maxn],ch[maxn * 1000][N],Na[maxn][N],Nb[maxn][N];
char A[maxn],B[maxn];
queue <Node> Q;
void Solve1()
{
int Ans = INF;
for (int i = 1; i <= na; i++)
{
int x = rt;
for (int j = i; j <= na; j++)
{
x = ch[x][A[j]];
if (!x) {Ans = min(Ans,j - i + 1); break;}
}
}
if (Ans == INF) puts("-1"); else cout << Ans << endl;
}
void Solve2()
{
int Ans = INF;
for (int i = 1; i <= na; i++)
{
int x = 0;
for (int j = i; j <= na; j++)
{
x = Nb[x][A[j]];
if (!x) {Ans = min(Ans,j - i + 1); break;}
}
}
if (Ans == INF) puts("-1"); else cout << Ans << endl;
}
void Solve3()
{
bool pass = 0; Q.push(Node(1,0,0));
while (!Q.empty())
{
Node k = Q.front(); Q.pop();
for (int i = 0; i < N; i++)
if (ch[k.x][i] && Na[k.y][i])
Q.push(Node(ch[k.x][i],Na[k.y][i],k.z + 1));
else if (!ch[k.x][i] && Na[k.y][i]) {pass = 1; cout << k.z + 1 << endl; break;}
if (pass) break;
}
if (!pass) puts("-1");
}
void Solve4()
{
for (int i = 0; i <= na; i++)
for (int j = 0; j <= nb; j++)
f[i][j] = INF;
f[0][0] = 0; int Ans = INF;
for (int i = 0; i <= na; i++)
for (int j = 0; j <= nb; j++)
{
if (f[i][j] == INF) continue;
for (int k = 0; k < N; k++)
{
if (Na[i][k] && Nb[j][k])
{
int &g = f[Na[i][k]][Nb[j][k]];
g = min(g,f[i][j] + 1);
}
else if (Na[i][k] && !Nb[j][k]) {Ans = min(Ans,f[i][j] + 1); break;}
}
}
if (Ans == INF) puts("-1"); else cout << Ans << endl;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
scanf("%s",A + 1); scanf("%s",B + 1);
na = strlen(A + 1); nb = strlen(B + 1);
for (int i = 1; i <= na; i++) A[i] -= 'a';
for (int i = 1; i <= nb; i++) B[i] -= 'a';
rt = cnt = 1;
for (int i = 1; i <= nb; i++)
{
int x = rt;
for (int j = i; j <= nb; j++)
{
if (!ch[x][B[j]]) ch[x][B[j]] = ++cnt;
x = ch[x][B[j]];
}
}
for (int i = na - 1; i >= 0; i--)
{
memcpy(Na[i],Na[i + 1],sizeof(Na[i + 1]));
Na[i][A[i + 1]] = i + 1;
}
for (int i = nb - 1; i >= 0; i--)
{
memcpy(Nb[i],Nb[i + 1],sizeof(Nb[i + 1]));
Nb[i][B[i + 1]] = i + 1;
}
Solve1(); Solve2(); Solve3(); Solve4();
return 0;
}