您的位置:首页 > 其它

HDU 6138 Fleet of the Eternal Throne AC自动机||后缀数组

2017-08-17 21:55 429 查看
传送门:HDU6138

题意:给出n个串和q次询问,每次询问给出x和y,表示输入的第x个和第y个串,要求找出一个最长的子串p,满足:p是x的子串,p是y的子串,且p是这n个串中某一个(可以是多个)的前缀,问p的最大长度是多少。

思路:看官方题解还很麻烦的样子,不过看dalao们的思路一下就懂了。。

将所有串插入到AC自动机里去,然后对于每个询问,先在AC自动机上查询x串,并对每一个经过的节点打上标记,代表从root到该节点形成的字符串是某个串的前缀,并且是x的子串,然后再查询y串,若经过了刚刚做标记的节点,则更新答案。

询问x串时不在节点上打标记,而是把所有经过的节点保存到set里,然后询问y串时再从set里找也可以,毕竟这题数据水。

后缀数组做法:

对于每次询问,将x串和y串链接起来(加分隔符),然后算出height数组,对于每个height[i]对应的子串,在字典树上查询其所对应的最长前缀,更新答案就好了。

代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100010;
int ans;
char s[MAXN];
vector<string> p;
struct Trie{
int next[MAXN][26], fail[MAXN], LEN[MAXN], FLAG[MAXN];
int root, L;
void insert(char buf[])
{
int len = strlen(buf), now = 0;
for(int i = 0; i < len; i++)
{
if(next[now][buf[i] - 'a'] == -1)
{
next[now][buf[i] - 'a'] = ++L;
LEN[L] = i + 1;
}
now = next[now][buf[i] - 'a'];
}
}
void init()//不要忘记初始化
{
memset(next, -1, sizeof(next));
memset(FLAG, 0, sizeof(int) * L);
root = L = 0;
}
void build()
{
queue<int>q;
fail[root] = root;
for(int i = 0; i < 26; i++)
if(next[root][i] == -1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
q.push(next[root][i]);
}
while(!q.empty())
{
int now = q.front(); q.pop();
for(int i = 0; i < 26; i++)
if(next[now][i] == -1)
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]] = next[fail[now]][i];
q.push(next[now][i]);
}
}
}
int query(int id, bool flag, int kk)
{
int len = p[id].size(); int now = root;
for(int i = 0; i < len; i++)
{
now = next[now][p[id][i] - 'a'];
int tmp = now;
while(tmp != root)
{
if(flag) FLAG[tmp] = kk;//is.insert(tmp);
else
{
if(FLAG[tmp] == kk)
ans = max(ans, LEN[tmp]);
}
tmp = fail[tmp];
}
}
}
};
Trie AC;
int main()
{
int T, n, q, x, y;
cin >> T;
while(T--)
{
AC.init();
p.clear();
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%s", s);
p.push_back(string(s));
AC.insert(s);
}
AC.build();
scanf("%d", &q);
while(q--)
{
scanf("%d %d", &x, &y);
x--,y--;
ans = 0;
AC.query(x, 1, q + 1);
AC.query(y, 0, q + 1);
printf("%d\n", ans);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: