jzoj4624NOIP2016A组模拟7.13KMP数学字符串匹配
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jzoj4624NOIP2016A组模拟7.13KMP数学字符串匹配相关的知识,希望对你有一定的参考价值。
【NOIP2016A组模拟7.13】字符串匹配
题面
Description
Input
Output
Sample Input
2
usaco
cowusacousa
Sample Output
3
Data Constraint
解题思路
一切的一切都因为一个%lld(((((((
易想, 做一段的KMP,求出一段的答案,然后用数学求出复制出n段的KMP
做一遍KMP(求出答案为A)
首尾相连会产生出更多的答案
将字符串倍长一遍,再做一个KMP(求出答案为A + B + A)
(A为单个段的答案,B为首尾合并产生的答案)
那么答案为((A + B) * n - B) (- B是因为最后复制的一段,后面没有连接的首尾,也就没有B)
Code
#include <iostream>
#include <cstring>
#include <cstdio>
#define ll unsigned long long
#define maxn 100100
using namespace std;
ll ans1, ans2, twice, once;
ll n, p[maxn * 2];
char a[maxn * 2], b[maxn];
void work1() { //第一遍KMP,求出A
ll lenb = strlen(b + 1), lena = strlen(a + 1);
for(int i = 1, j = 0; i < lenb; i++) {
while(j > 0 && b[j + 1] != b[i + 1])
j = p[j];
if(b[j + 1] == b[i + 1]) j++;
p[i + 1] = j;
}
for(int i = 0, j = 0; i < lena; i++) {
while(j > 0 && b[j + 1] != a[i + 1])
j = p[j];
if(b[j + 1] == a[i + 1]) j++;
if(j == lenb)
ans1++, j = p[j];
}
}
void work2() { //第二遍KMP,求出A + B + A
ll lenb = strlen(b + 1), lena = strlen(a + 1);
for(int i = 1, j = lena + 1; i <= lena; i++, j++)
a[j] = a[i];
lena = strlen(a + 1);
for(int i = 0, j = 0; i < lena; i++) {
while(j > 0 && b[j + 1] != a[i + 1])
j = p[j];
if(b[j + 1] == a[i + 1]) j++;
if(j == lenb)
ans2++, j = p[j];
}
}
int main() {
scanf("%lld", &n);
scanf("%s", b + 1);
scanf("%s", a + 1);
work1();
work2();
twice = ans2 - ans1; //twice = (A + B + A) - A = A + B
once = twice * 2 - ans2; //once = (A + B) * 2 - (A + B + A) = B
printf("%lld", twice * n - once); //(A + B) * 2 - B
}
以上是关于jzoj4624NOIP2016A组模拟7.13KMP数学字符串匹配的主要内容,如果未能解决你的问题,请参考以下文章
Jzoj4742NOIP2016提高A组模拟9.2快速幂单峰
jzoj3508NOIP2013模拟11.5B组DAY 1 (7.12)HASH好元素(good)
jzoj3510NOIP2013模拟11.5B组DAY 1 (7.12)DP最短路径(path)