#1261 : String Problem II
-
5 5 dsxmlkxp asxglqkdxp asxgavxp asxglp sxglkx kebvpyky hjpntqft asxglkxp polbmzgq jdczlmtd
Sample Output -
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 -1 -1 1 3 -1 4 5 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
Description
We have a set of strings S which contains N distrinct strings.
We have also M queries, each query with a string w, asking you three questions:
1. Output the three strings with the smallest index among all strings in S which can be obtained by adding exactly two characters to w.
2. Output the three strings with the smallest index among all strings in S which can be obtained by modifying no more than two characters of w.
3. Output the three strings with the smallest index among all strings in S which can be obtained by deleting exactly two characters of w.
The character can be added anywhere including before the head and after the tail.
All strings only contain lowercase letters.
Input
First line with two integers N and M, denoting the number of strings in S and the number of queries.
The following N lines, the i-th line giving the i-th string in S whose index is i.
THe following M lines, the i-th line giving the i-th query string.
Data Limit:
N,M<=10000
The sum of length of strings in S <=100000
The sum of length of all query strings <=100000
Output
For each query, output three lines with three numbers on each line indicating the three indexes in a increasing order.
If there are less than three strings meeting the requirements, output -1.
For example, if the strings meeting the requirements are 1 and 2, you should ouput 1 2 -1.
题意:给定一个保护N个模式串的集合S和M次查询,每次查询给出一个字符串str,问
1,在串str任意位置增加2个字符能够得到的模式串,找到三个下标最小的,升序输出3个下标,不够3个时输出-1。
2,串str最多修改2个字符能够得到的模式串,找到三个下标最小的,升序输出3个下标,不够3个时输出-1。
3,在串str任意位置删除2个字符能够得到的模式串,找到三个下标最小的,升序输出3个下标,不够3个时输出-1。
思路:建trie树,然后就是DFS。这里坑了好久。。。
第一种情况:当遍历到串str的末尾时,即使增加的字符不够2个,还是可以沿着trie边继续DFS的——只需在末尾前增加一个和末尾相同的字符即可。
第二种情况:当遍历到串str的末尾时,如果修改的字符不超过2个,是不能继续沿着trie边继续DFS的。
第三种情况:当遍历到串str的末尾时,如果删除的字符不够2个,也是不能继续沿着trie边继续DFS的。对于这种情况,我们是可以停留在trie的某个节点上通过删除str的字符继续DFS的。
AC代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (100000+10)
#define MAXM (500000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
bool vis[10001];
struct Trie
{
int next[MAXN][30], L, root, id[MAXN];
int newnode()
{
for(int i = 0; i < 26; i++)
next[L][i] = -1;
id[L++] = -1;
return L-1;
}
void init()
{
L = 0;
root = newnode();
}
void Insert(char *s, int ID)
{
int u = root, v;
for(int i = 0; s[i]; i++)
{
int v = s[i] - 'a';
if(next[u][v] == -1)
next[u][v] = newnode();
u = next[u][v];
}
id[u] = ID;
}
int ans1, ans2, ans3;
void Update(int ID)
{
int a[4];
a[0] = ans1 == -1 ? INF : ans1;
a[1] = ans2 == -1 ? INF : ans2;
a[2] = ans3 == -1 ? INF : ans3;
a[3] = ID;
sort(a, a+4);
ans1 = a[0] == INF ? -1 : a[0];
ans2 = a[1] == INF ? -1 : a[1];
ans3 = a[2] == INF ? -1 : a[2];
vis[ID] = true;
}
void DFS(int u, int use, int pos, char *s, int op)
{
switch(op)
{
case 1: if(!s[pos] && use == 2)
{
if(id[u] != -1 && !vis[id[u]])
Update(id[u]);
}
else //if(use <= 2)
{
for(int i = 0; i < 26; i++)
{
if(next[u][i] == -1) continue;
if(s[pos] == 'a' + i)
DFS(next[u][i], use, pos+1, s, op);
if(use < 2)
DFS(next[u][i], use+1, pos, s, op);
}
}
break;
case 2: if(!s[pos])// && use <= 2)
{
if(use <= 2 && id[u] != -1 && !vis[id[u]])
Update(id[u]);
}
else
{
//if(!s[pos+1]) break;
for(int i = 0; i < 26; i++)
{
if(next[u][i] == -1) continue;
if(s[pos] == 'a' + i)
DFS(next[u][i], use, pos+1, s, op);
else if(use < 2)
DFS(next[u][i], use+1, pos+1, s, op);
}
}
break;
case 3: if(!s[pos]) //&& use == 2)
{
if(use == 2 && id[u] != -1 && !vis[id[u]])
Update(id[u]);
}
else
{
//if(!s[pos+1]) break;
for(int i = 0; i < 26; i++)
{
if(next[u][i] == -1) continue;
if(s[pos] == 'a' + i)
DFS(next[u][i], use, pos+1, s, op);
//else if(use < 2)
// DFS(u, use+1, pos+1, s, op);
}
if(use < 2)
DFS(u, use+1, pos+1, s, op);
}
}
}
};
Trie tree;
char str[MAXN];
void solve(int op)
{
CLR(vis, false); tree.ans1 = tree.ans2 = tree.ans3 = -1;
tree.DFS(tree.root, 0, 0, str, op);
printf("%d %d %d\n", tree.ans1, tree.ans2, tree.ans3);
}
int main()
{
int N, M;
while(scanf("%d%d", &N, &M) != EOF)
{
tree.init();
for(int i = 0; i < N; i++)
{
Rs(str);
tree.Insert(str, i+1);
}
W(M)
{
Rs(str);
solve(1); solve(2); solve(3);
}
}
return 0;
}