标签:others memory ret otto time 方便 pac 不用 tle
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 256000/256000 K (Java/Others)
Total Submission(s): 2523 Accepted Submission(s): 934
题目链接:HDU 6153
扩展KMP解决的是对于每一个每一个$S$的后缀$Suffix(i)$,它与$T$串最长的公共前缀是多少,即它与$T$串各自从头开始能匹配几个,一旦有一个不匹配即结束。
这题求的是每一个$S_2$的后缀出现在$S_1$有几次,那么我们可以把两个串都反过来变成求$S_2$的前缀在$S_1$出现过几次,这样就可以发现如果$S_2$的前缀$prefix(j)$与$S_1$的后缀$Suffix(i)$的最长公共前缀为$k$,那么包括$prefix(j)$以及$j$以前的前缀均在$S_1$的$i$处出现过一次,贡献为$(k+1)*k/2$,那么这样求一遍$extend[]$数组后统计答案即可
代码:
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <string>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 1e6 + 7;
const LL mod = 1000000007LL;
char s[N], t[N];
int nxt[N], ex[N];
void getnxt(char T[], int len, int nxt[])
{
nxt[0] = len;
int a;
int p;
for (int i = 1, j = -1; i < len; i++, j--)
{
if (j < 0 || i + nxt[i - a] >= p)
{
if (j < 0)
p = i, j = 0;
while (p < len && T[p] == T[j])
p++, j++;
nxt[i] = j;
a = i;
}
else
nxt[i] = nxt[i - a];
}
}
void getextend(char S[], char T[], int ls, int lt, int extend[], int nxt[])
{
getnxt(T, lt, nxt); //得到next
int a;
int p; //记录匹配成功的字符的最远位置p,及起始位置a
for (int i = 0, j = -1; i < ls; i++, j--) //j即等于p与i的距离,其作用是判断i是否大于p(如果j<0,则i大于p)
{
if (j < 0 || i + nxt[i - a] >= p) //i大于p(其实j最小只可以到-1,j<0的写法方便读者理解程序),
{ //或者可以继续比较(之所以使用大于等于而不用等于也是为了方便读者理解程序)
if (j < 0)
p = i, j = 0; //如果i大于p
while (p < ls && j < lt && S[p] == T[j])
p++, j++;
extend[i] = j;
a = i;
}
else
extend[i] = nxt[i - a];
}
}
int main(void)
{
int T, i;
scanf("%d", &T);
while (T--)
{
scanf("%s%s", s, t);
int la = strlen(s);
int lb = strlen(t);
reverse(s, s + la);
reverse(t, t + lb);
getnxt(t, lb, nxt);
getextend(s, t, la, lb, ex, nxt);
LL ans = 0;
for (i = 0; i < la; ++i)
{
LL temp = (LL)ex[i] * ((LL)ex[i] + 1LL) / 2LL;
ans = (ans + temp) % mod;
}
printf("%I64d\n", ans);
}
return 0;
}
标签:others memory ret otto time 方便 pac 不用 tle
原文地址:http://www.cnblogs.com/Blackops/p/7545696.html