NKOJ 密码 [暴力]
问题描述
假发通过了不懈的努力,得到了将军家门锁的密码(一串小写英文字母)。但是假发被 十四和猩猩他们盯上了,所以假发需要把密码传递出去。因为假发不想十四他们发现几松门 前贴的小纸条就是将军家的密码,所以他加密了密码(新八:听起来有点诡异)。加密方法 如下:随机地,在密码中任意位置插入随机长度的小写字符串。 不过,假发相信银桑和他那么多年小学同学,一定能猜中密码是什么的(新八:银桑什 么时候成攮夷志士了!!!)。可是,写完了小纸条之后,假发觉得有点长,就想截去头和 尾各一段(可以为空),让剩下的中间那一段依然包含真~密码。想着想着,假发就想知道 有多少种可行方案。结果在沉迷于稿纸之际,假发被投进了狱门岛(新八:……)。于是, 就由你计算了。
输入格式
两行非空字符串,纯小写英文字母,第一行是加密后的密码,第二行是原密码。
第一行长度不超过 300000,第二行不超过 200。
输出格式
一行,有多少种方案。注意:不剪也是一种方案。
题解
好像没什么特别的算法…乘法原理??
设 为在新密码串中扫动的指针, 为在原密码串(真密码)中扫动的指针。解题的关键就在于不停地扫动 和 指针。固定原密码串,一位一位地在新密码串中匹配真密码。当匹配完一串真密码时,更新答案(注意是上一次匹配到的密码串的开头位置 与这一次的开头位置 的差,即 。不能不记录 ,否则会造成重复计算),并把 移到 的位置<千万不要忘记T^T>, 移到原密码的第一位,然后重复以上操作。
注意细节(不剪也是一种方案)。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s1[300050],s2[250];
int main(){
scanf("%s%s",s1+1,s2+1);
int len1=strlen(s1+1),len2=strlen(s2+1);
int i=1,j=1,Last,Cur=0;
long long Ans=0;
while(i<=len1){
while(i<=len1 && s1[i]!=s2[j])i++;
if(i>len1)break;
if(j==1)Last=Cur,Cur=i;
if(j==len2)Ans+=(long long)(Cur-Last)*(len1-i+1);
i++,j++;
if(j>len2)j=1,i=Cur+1;
}
printf("%lld",Ans);return 0;
}