POJ3415 Common Substrings 【后缀数组 + 单调栈】
时间限制: 5000MS | 内存限制: 65536K | |
提交总数: 11942 | 接受: 4051 |
描述
字符串T的子字符串被定义为:
Ť(我,ķ)= Ť 我 Ť 我 1 ... Ť I
+ K -1,1≤ 我 ≤ I + K -1≤| T |。
给定两个字符串A,B和一个整数K,我们定义S,一组三元组(i,j,k):
S = {(i,j,k)| ķ ≥ ķ,甲(我,ķ)= 乙(Ĵ,ķ)}。
你要给的价值| S | 特定甲,乙和ķ。
输入
输入文件包含几个数据块。对于每个块,第一行包含一个整数ķ,随后包含字符串两行阿和乙分别。输入文件以K =
0 结尾。
1≤| A |,| B | ≤10 5
1≤ ķ ≤ 分钟 {| A |,| B |} A和B的
字符都是拉丁字母。
产量
对于每种情况,输出一个整数| S |。
示例输入
- 2
- aababaa
- abaabaa
- 1
- XX
- XX
- 0
示例输出
- 22
- 五
蜜汁翻译。。额不要在意
挺难的一题,弱弱的我码了一个中午
首先后缀数组双串匹配,同样的操作,两串链接用一字符隔开,跑一遍sa
重点就是如何求出公共前缀大于等于K的子串数
首先如果lcp(i,j) = len 【len >k】那么len - 1也满足
所以对于lcp(i,j),它的贡献是len - k + 1
我们利用height数组分组,每一个组内的AB串都可以匹配,统计答案即可
但这样会T,因为这样做其实是O(n^2)的
怎么办呢?
我们需要维护一个单调栈,扫两次
第一次:对于每个A,统计它前面的B对于答案的贡献
我们知道两串在height数组之间的最小值即为其最长公共前缀长度,
对于A前第一个B之后的一个最小值,一定会影响到之前左右的B,但是B与B之间的最小值只会影响到前面的B而不影响到后面的B
因此我们维护一个单调递增单调栈,如果当前height比栈顶小,那么栈顶所对应的那些后缀会受到此height的影响【 因为之前的B到后面的A一定会跨过这个地方,而这个地方height较小】,就合并栈顶【注意是合并】
看代码吧
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<map>
- #include<algorithm>
- #define LL long long int
- #define REP(i,n) for (int i = 1; i <= (n); i++)
- #define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
- using namespace std;
- const int maxn = 200005,maxm = 100005,INF = 1000000000;
- inline int RD(){
- int out = 0,flag = 1; char c = getchar();
- while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
- while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
- return out * flag;
- }
- char s[maxn],B[maxn];
- int sa[maxn],rank[maxn],height[maxn],t1[maxn],t2[maxn],c[maxn],n,m,K,lA;
- void SA(){
- int *x = t1,*y = t2;
- for (int i = 0; i <= m; i++) c[i] = 0;
- for (int i = 1; i <= n; i++) c[x[i] = s[i]]++;
- for (int i = 1; i <= m; i++) c[i] += c[i - 1];
- for (int i = n; i >= 1; i--) sa[c[x[i]]--] = i;
- for (int k = 1; k <= n; k <<= 1){
- int p = 0;
- for (int i = n - k + 1; i <= n; i++) y[++p] = i;
- for (int i = 1; i <= n; i++) if (sa[i] - k > 0) y[++p] = sa[i] - k;
- for (int i = 0; i <= m; i++) c[i] = 0;
- for (int i = 1; i <= n; i++) c[x[y[i]]]++;
- for (int i = 1; i <= m; i++) c[i] += c[i - 1];
- for (int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i];
- swap(x,y);
- p = 1; x[sa[1]] = 1;
- for (int i = 2; i <= n; i++)
- x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? p : ++p;
- if (p >= n) break;
- m = p;
- }
- REP(i,n) rank[sa[i]] = i;
- int k = 0;
- REP(i,n){
- if (k) k--;
- int j = sa[rank[i] - 1];
- while (s[i + k] == s[j + k]) k++;
- height[rank[i]] = k;
- }
- }
- pair<int,int> st[maxn];
- int top;
- LL ans;
- void solve(){
- LL sum = 0; top = 0;
- for (int i = 2; i <= n; i++){
- if (height[i] < K){
- top = 0; sum = 0;
- }else {
- int num = 0;
- if (sa[i - 1] > lA + 1) num++,sum += height[i] - K + 1;
- while (top && height[i] <= st[top].first){
- sum -= st[top].second * (st[top].first - height[i]);
- num += st[top--].second;
- }
- st[++top] = make_pair(height[i],num);
- if (sa[i] <= lA) ans += sum;
- }
- }
- top = 0; sum = 0;
- for (int i = 2; i <= n; i++){
- if (height[i] < K){
- top = 0; sum = 0;
- }else {
- int num = 0;
- if (sa[i - 1] <= lA) num++,sum += height[i] - K + 1;
- while (top && height[i] <= st[top].first){
- sum -= st[top].second * (st[top].first - height[i]);
- num += st[top--].second;
- }
- st[++top] = make_pair(height[i],num);
- if (sa[i] > lA + 1) ans += sum;
- }
- }
- }
- int main(){
- while (K = RD()){
- scanf("%s",s + 1); lA = strlen(s + 1); strcat(s + 1,"#");
- scanf("%s",B + 1); strcat(s + 1,B + 1);
- ans = 0; m = 256; n = strlen(s + 1);
- SA();
- solve();
- printf("%lld\n",ans);
- }
- return 0;
- }
POJ3415 Common Substrings 【后缀数组 + 单调栈】的更多相关文章
- POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数
题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K ...
- POJ3415 Common Substrings(后缀数组 单调栈)
借用罗穗骞论文中的讲解: 计算A 的所有后缀和B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于k 的部分全部加起来.先将两个字符串连起来,中间用一个没有出现过的字符隔开.按height ...
- poj 3415 Common Substrings 后缀数组+单调栈
题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...
- poj 3415 Common Substrings——后缀数组+单调栈
题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...
- poj 3415 Common Substrings —— 后缀数组+单调栈
题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...
- poj3415 Common Substrings (后缀数组+单调队列)
Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 9414 Accepted: 3123 Description A sub ...
- 【BZOJ-3238】差异 后缀数组 + 单调栈
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1561 Solved: 734[Submit][Status] ...
- BZOJ_3879_SvT_后缀数组+单调栈
BZOJ_3879_SvT_后缀数组+单调栈 Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个 ...
- BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈
BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...
- BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)
BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...
随机推荐
- stm32f103 time2配置,转载
//----------------------------main()-------------------- //stm32f103c8t6有3个普通1个高级定时器 //每次进入中断服务程序间隔时 ...
- Python自动化运维——系统进程管理模块
Infi-chu: http://www.cnblogs.com/Infi-chu/ 模块:psutil psutil是一个跨平台库,可以很轻松的为我们实现获取系统运行的进程和资源利用率等信息. 功能 ...
- Servlet生命周期与线程安全
上一篇介绍了Servlet初始化,以及如何处理HTTP请求,实际上在这两个过程中,都伴随着Servlet的生命周期,都是Servlet生命周期的一部分.同时,由于Tomcat容器默认是采用单实例多线程 ...
- kafka单机部署文档
单机Kafka部署文档 最简单的使用方式,单机,使用自带的zookeeper 1.解压 下载地址:http://pan.baidu.com/s/1i4K2pXr tar –zxvf kafka_2.1 ...
- ArcPy:GeoJSON转ArcGIS Geometry
import arcpy geojson = {"type":"Polygon","coordinates":[[[120.81878662 ...
- python 字典(dict)按键和值排序
python 字典(dict)的特点就是无序的,按照键(key)来提取相应值(value),如果我们需要字典按值排序的话,那可以用下面的方法来进行: 1 下面的是按照value的值从大到小的顺序来排序 ...
- 『MongoDB』集合更新操作
参考 定义 db.collection.update(query, update, options) 改变一个在集合中已经存在的文档或文档数组.默认的,update()方法更新一个独立的文档.如果mu ...
- github简单使用教程(转)
github是一个基于git的代码托管平台,付费用户可以建私人仓库,我们一般的免费用户只能使用公共仓库,也就是代码要公开.对于一般人来说公共仓库就已经足够了,而且我们也没多少代码来管理,O(∩_∩)O ...
- C计算了一下
#include <stdio.h> int main(){ int a,b,c,e; a=6 + 5 / 4 - 2; b=2 + 2 * (2 * 2 - 2) % 2 / 3; c= ...
- 孤荷凌寒自学python第七十一天开始写Python的第一个爬虫
孤荷凌寒自学python第七十一天开始写Python的第一个爬虫 (完整学习过程屏幕记录视频地址在文末) 在了解了requests模块和BeautifulSoup模块后,今天开始真正写一个自己的爬虫代 ...