真的很奇怪,在其他OJ上交了,速度很快排到第二(最慢一个点80ms)。。但是用内存挺多的。
交USACO的时候,在用了15.8M内存的时候RE了。 我猜是限了16M内存。 看来不能省事……我得去重写了
/*
TASK:prefix
LANG:C++
*/
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
char s[220][220], text[200115];
int next[220000];
int stail = 0;
struct edge
{
int v;
edge *next;
edge()
{
v = - 1;
next = NULL;
}
edge(int x, edge *p)
{
v = x;
next = p;
}
}*a[200005]={NULL};//v
void init()
{
while (1)
{
scanf("%s", s[stail++]);
if (s[stail - 1][0] == '.')
{
-- stail;
break;
}
}
int textlen = 0;
char ch;
while ((ch = getchar()) != EOF)
{
if (ch == '\n') continue;
text[textlen++] = ch;
}
text[textlen] ='\0';
for (int i = 0; i != 200005; ++ i)a[i] =NULL;
}
inline void ins(int x, int y) // x可以到y
{
a[x] = new edge(y, a[x]);
}
inline void kmp(char *son, char *text, int son_length, int text_length)
{
int i = 0, j = -1;
next[0] = -1;
while (i != son_length)
{
if (j == -1 || son[i] == son[j]) next[++i] = ++j;
else j = next[j];
}
i = 0, j = 0;
while (i != text_length)
{
if (j == -1 || text[i] == son[j]) ++i, ++j;
else j = next[j];
if (j == son_length) //j已经超出范围了
{
ins(i - son_length, i);
j = next[j];
}
}
}
queue<int>q;
bool vis[200005]={0};
void doit()
{
for (int i = 0; i != stail; ++ i) kmp(s[i], text, strlen(s[i]), strlen(text));
q.push(0);
vis[0] = true;
while (!q.empty())
{
int now = q.front();
q.pop();
for (edge *i = a[now]; i != NULL; i = i -> next)
{
int will = i -> v;
if (!vis[will])
{
vis[will] = true;
q.push(will);
}
}
}
int tmp = strlen(text);
for (int i = tmp; i >= 0; -- i) if (vis[i]) {printf("%d\n", i); return;}
}
int main()
{
freopen("prefix.in","r",stdin);
freopen("prefix.out","w",stdout);
init();
doit();
return 0;
}
写了一个暴力的…… 然后尼玛这么快? 在BSOJ上居然是第一……(上面的KMP是第三)
Executing... Test 1: TEST OK [0.008 secs, 3896 KB] Test 2: TEST OK [0.008 secs, 3896 KB] Test 3: TEST OK [0.005 secs, 3896 KB] Test 4: TEST OK [0.008 secs, 3896 KB] Test 5: TEST OK [0.005 secs, 3896 KB] Test 6: TEST OK [0.041 secs, 3896 KB]
但是不爆内存了显然~而且速度快。显然是数据弱了……但是实际上如果极限数据,2个算法的时间复杂度应该差不多,毕竟串短……,但是显然后者更节约内存
方法: 从0位置开始,把每个串都匹配一下…… 如果从4位置开始,匹配了一个长度3的串,那么把7塞进队列。 因为5,6根本不用匹配了,因为没有串以他们为结尾……
/*
TASK:prefix
LANG:C++
*/
#include <cstdio>
#include <cstring>
#include <queue>
char s[201][11], text[200005];
int length[201];
bool vis[200005]={1,0};
int stail = 0, textlen=0;
inline void init()
{
while (1)
{
scanf("%s", s[stail++]);
length[stail - 1] = strlen(s[stail - 1]);
if (s[stail - 1][0] == '.')
{
-- stail;
break;
}
}
char ch;
while ((ch = getchar()) != EOF)
{
if (ch == '\n') continue;
text[textlen++] = ch;
}
for (int i = 0; i != 15; ++ i) text[textlen++] = '#';
text[textlen] ='\0';
}
std::queue<int>q;
inline bool check(char *son, char *text, int son_length)
{
for (int i = 0; i != son_length; ++ i)
if (son[i] != text[i]) return false;
return true;
}
inline void doit()
{
int i, will, ans = 0;
q.push(0);
while (!q.empty())
{
ans = q.front();
q.pop();
for (i = 0; i != stail; ++ i)
{
will = ans + length[i];
if (vis[will]) continue;
if (check(s[i],text+ans, length[i]))
{
vis[will] = 1;
q.push(will);
}
}
}
printf("%d\n",ans);
}
int main()
{
freopen("prefix.in","r",stdin);
freopen("prefix.out","w",stdout);
init();
doit();
return 0;
}