Description:
Input:
Output:
Sample Input:
3
3
wellplayed
thankyou
pyroblast
2
a*abc
abc*a
2
a*abc
a1234567890abc
Sample Output:
N
N
Y
Data Constraint:
题目大意:
字符串中,*可以替代成任何长度任何模样的字符串,给出T组,每组n个字符串,求两两之间是否能匹配。
题解:
如果n个字符串都带星号,只需要判断字符串的第一个星号之前的字符串是否完全相同,最后一个星号的字符串是否完全相同。
如果有一个不带星号的字符串,用它去和其它的匹配,假设它是A串,待匹配的串是B串,只需要判断星号之间的字符串是否按顺序地出现在A串,用KMP解决即可。
Code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define fd(i, x, y) for(int i = x; i >= y; i --)
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
using namespace std;
const int Maxc = 20000005, Maxn = 100005;
int T, n, l[Maxn], r[Maxn], p[Maxn];
int next[Maxc];
char c[Maxc];
bool pd(int x, int y) {
if(!p[x] && !p[y]) {
if(r[x] - l[x] != r[y] - l[y]) return 0;
fo(i, 0, r[x] - l[x]) if(c[l[x] + i] != c[l[y] + i]) return 0;
return 1;
}
if(!p[x]) swap(x, y);
int u = 0, v = 0;
fo(i, l[x], r[x]) {if(c[i] == '*') break; u ++;}
fd(i, r[x], l[x]) {if(c[i] == '*') break; v ++;}
if(!p[y] && u + v > r[y] - l[y] + 1) return 0;
fo(i, 0, u - 1) {
if(c[l[y] + i] == '*') break;
if(c[l[y] + i] != c[l[x] + i]) return 0;
}
fo(i, 0, v - 1) {
if(c[r[y] - i] == '*') break;
if(c[r[y] - i] != c[r[x] - i]) return 0;
}
return 1;
}
void Get_next(int x, int y) {
next[x] = 0;
int i = 0;
fo(j, x + 1, y) {
while(i > 0 && c[x + i] != c[j]) i = next[x + i - 1];
if(c[x + i] == c[j]) i ++;
next[j] = i;
}
}
void Work() {
int ans = 1, bz = 0;
scanf("%d", &n);
fo(i, 1, n) {
l[i] = r[i - 1] + 1; r[i] = r[i - 1];
char ch = ' '; for(;! ((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '*'); ch = getchar());
for(; (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '*'; ch = getchar())
c[++ r[i]] = ch;
p[i] = 0;
fo(j, l[i], r[i]) if(c[j] == '*') p[i] = 1;
if(!p[i]) bz = 1;
}
if(bz == 0) {
fo(i, 1, n) {
fo(j, i + 1, n) if(!pd(i, j)) {
ans = 0; break;
}
if(ans == 0) break;
}
if(ans) printf("Y\n"); else printf("N\n");
return;
}
fo(k, 1, n) if(!p[k]) bz = k;
fo(k, 1, n) if(k != bz) {
if(!pd(bz, k)) {
ans = 0; break;
}
if(!p[k]) continue;
int st = l[bz], en = r[bz], st2 = l[k], en2 = r[k];
fo(i, l[k], r[k]) {
if(c[i] == '*') break;
st ++; st2 ++;
}
fd(i, r[k], l[k]) {
if(c[i] == '*') break;
en --; en2 --;
}
while(st2 < en2) {
st2 ++;
fo(d, st2, en2) {
if(c[d] == '*') {
if(st2 == d) break;
Get_next(st2, d - 1);
int i = 0, bz = 0;
fo(j, st, en) {
while(i && c[st2 + i] != c[j]) i = next[st2 + i - 1];
if(c[st2 + i] == c[j]) i ++;
if(i == d - st2) {
bz = 1;
st = j + 1;
st2 = d;
break;
}
}
if(!bz) ans = 0;
break;
}
}
if(ans == 0) break;
}
if(ans == 0) break;
}
if(ans) printf("Y\n"); else printf("N\n");
}
int main() {
freopen("hs.in", "r", stdin);
freopen("hs.out", "w", stdout);
for(scanf("%d", &T); T; T --)
Work();
}