2019年华南理工大学程序设计竞赛(春季赛) K Parco_Love_String(后缀自动机)找两个串的相同字串有多少
https://ac.nowcoder.com/acm/contest/625/K
题意:
给出Q 个询问 i , 求 s[0..i-1] 与 s[i...len-1] 有多少相同的字串
分析:
给出了查询 , 容易想到先预处理出答案好吧 , 字符串的问题也容易想到后缀自动机 ,但是我们该怎么使用呢?
下面提供我的思路;
我们建立出SAM后 , 跑一边拓扑排序 ,根据SAM跑出来的拓扑排序的序列特性 , 我们可以求出 在当前状态st 的最大串字符出现的个数
for (int i = now; i >= ; --i) {///得到的是最大字符串的出现次数
int x = rank[i];
endpos[slink[x]] += endpos[x];
}
可是这次我们需要求的是相同的串有多少 , 我们不可以暴力出SAM里面存有的串的个数 , 现在就来搞一个很奇妙的东西,
我们可以根据上面求出来的endpos , 去推出 有多少相同的字符串;
for(int i= ; i<=now; i++)///得到全部串的出现次数
{
int x=rank[i]; ///到x这个状态时 , 有多少的后缀总共串
sum[x] = sum[slink[x]] + endpos[x]*(maxlen[x] - maxlen[slink[x]]);
//cout<<sum[x]<<endl;
}
我们知道 对于 now1 , 与now2=slink[now1] , 如果now1状态出现了 , 那么now2 的状态也肯定会出现 , 因为silnk 是链接now1接下去的后缀 ,也就是说now2 是now1的后缀
所以我们求当前now 有多少串相同的时候 , 就要+上一个的后缀价值 sum[x] = sum[slink[x]】 + 当前的价值
当前的价值又是 怎么计算呢?
我们知道 maxlen[x] - maxlen[slink[x]] 是表示当前的状态x 里面有多少的串 , 那这个状态出现的次数与包含的串相乘 , 不就是当前我们需要求的价值了吗
上面可能说的比较乱 , 主要是我巨菜不知如何表达鸭
上面是用str1 串去构建的SAM , 然后用str2 在这个自动机里面跑 , 与求LCA 很相似
可以参考https://www.cnblogs.com/shuaihui520/p/10686862.html
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
#define ll long long
using namespace std;
const int maxn = ;
struct SAM{ int trans[maxn<<][], slink[maxn<<], maxlen[maxn<<];
// 用来求endpos
int indegree[maxn<<], endpos[maxn<<], rank[maxn<<], ans[maxn<<];
// 计算所有子串的和(0-9表示)
LL sum[maxn<<],D[maxn];
int last, now, root; inline void newnode (int v) {
maxlen[++now] = v;
mem(trans[now],);
} inline void extend(int c) {
newnode(maxlen[last] + );
int p = last, np = now;
// 更新trans
while (p && !trans[p][c]) {
trans[p][c] = np;
p = slink[p];
}
if (!p) slink[np] = root;
else {
int q = trans[p][c];
if (maxlen[p] + != maxlen[q]) {
// 将q点拆出nq,使得maxlen[p] + 1 == maxlen[q]
newnode(maxlen[p] + );
int nq = now;
memcpy(trans[nq], trans[q], sizeof(trans[q]));
slink[nq] = slink[q];
slink[q] = slink[np] = nq;
while (p && trans[p][c] == q) {
trans[p][c] = nq;
p = slink[p];
}
}else slink[np] = q;
}
last = np;
// 初始状态为可接受状态
endpos[np] = ;
} inline void init()
{
root = last = now = ;
slink[root]=;
mem(trans[root],);
mem(endpos,);
mem(sum,);
mem(indegree,);
mem(rank,);
} inline void getEndpos() {
// topsort
for (int i = ; i <= now; ++i) indegree[ maxlen[i] ]++; // 统计相同度数的节点的个数
for (int i = ; i <= now; ++i) indegree[i] += indegree[i-]; // 统计度数小于等于 i 的节点的总数
for (int i = ; i <= now; ++i) rank[ indegree[ maxlen[i] ]-- ] = i; // 为每个节点编号,节点度数越大编号越靠后
// 从下往上按照slik更新
for (int i = now; i >= ; --i) {///得到的是最大字符串的出现次数
int x = rank[i];
endpos[slink[x]] += endpos[x];
}
for(int i= ; i<=now; i++)///得到全部串的出现次数
{
int x=rank[i]; ///到x这个状态时 , 有多少的后缀总共串
sum[x] = sum[slink[x]] + endpos[x]*(maxlen[x] - maxlen[slink[x]]);
//cout<<sum[x]<<endl;
}
}
///用一个串去跑的自动机
inline void work(string s,int W)
{
getEndpos();
int len=s.size();
int now=root;
int t1=;
ll ret=;
for(int i= ; i<len ; i++)
{
int nowid=s[i]-'a';
if(trans[now][nowid])///这个状态有了 , 去下一个状态找
{
t1++;
now=trans[now][nowid];
//ret+=sum[slink[now]] + endpos[now]*(t1-maxlen[slink[now]]);
}
else
{ while(now!= && trans[now][nowid]==) {now=slink[now];}///缩小范围找满足条件的 if(now)
{
t1 = maxlen[now]+;
now=trans[now][nowid]; }
else
{
t1=;now=root;
}
}
ret+=sum[slink[now]] + endpos[now]*(t1-maxlen[slink[now]]);
}
D[W]=ret;
//return ret;
} }sam; int main()
{ string T;cin>>T;
int len=T.size(); for(int i= ; i<len ; i++)
{
string t2;
sam.init();
for(int j= ; j<i ; j++)
{
sam.extend(T[j]-'a');
} for(int j=i ; j<len ; j++)
{
t2+=T[j];
}
sam.work(t2,i); }
int E;scanf("%d",&E);
while(E--)
{
int x;
scanf("%d",&x);
printf("%lld\n",sam.D[x]);
} //- sam.all();
}
2019年华南理工大学程序设计竞赛(春季赛) K Parco_Love_String(后缀自动机)找两个串的相同字串有多少的更多相关文章
- A NB群友 【记忆化搜索】(2019年华南理工大学程序设计竞赛(春季赛))
冲鸭!去刷题:https://ac.nowcoder.com/acm/contest/625/A 题目描述 CC是著名的算法竞赛选手,他不仅人长得帅,而且技术了得,自然而然就有了许多粉丝. 为了能帮助 ...
- 2019年华南理工大学程序设计竞赛(春季赛)-C-六学家的困惑
题目链接:https://ac.nowcoder.com/acm/contest/625/C 题意:给定两个字符串,每次只能从两个字符串的两端取字符,求依次取字符后所构成的数字最大为多少. 思路:思路 ...
- 2019年华南理工大学程序设计竞赛(春季赛)-H-Parco_Love_GCD
题目链接:https://ac.nowcoder.com/acm/contest/625/H 题意:给定n个数(<=1e9)的序列,其中n<=5e5,求该序列所有子序列的对应的gcd对1e ...
- C 六学家的困惑 【YY】 (2019年华南理工大学程序设计竞赛(春季赛))
冲鸭,去刷题:https://ac.nowcoder.com/acm/contest/625/C 小六喜欢两全其美的事情,今天就正好有一个这样的机会. 小六面前有两根管子,管子里面放满了数字为1到9的 ...
- 2019年华南理工大学程序设计竞赛(春季赛) B 修仙时在做什么?有没有空?可以来炼丹吗?(思维建图搜索)
https://ac.nowcoder.com/acm/contest/625/B 分析: 全部的状态只有1<<18 个 , 所以我们可以预处理 f[u][j] , 然后建立出全部的u可以 ...
- 2019年华南理工大学程序设计竞赛(春季赛)A NB群友
https://ac.nowcoder.com/acm/contest/625/A 题意:给出一个区间范围 , 求有多少个数的每一位的积是在这个区间里面的 分析:没错了 ,就是记忆化暴力搜索 ,不断的 ...
- 2018华南理工大学程序设计竞赛 H-对称与反对称
H-对称与反对称 题目描述 给出一个N*N的方阵A.构造方阵B,C: 使得A = B + C.其中 B为对称矩阵,C为反对称矩阵. 对于方阵S中的任意元素,若(S)ij = (S)ji,则称S为对称矩 ...
- “景驰科技杯”2018年华南理工大学程序设计竞赛 B. 一级棒!(并查集)
题目链接:https://www.nowcoder.com/acm/contest/94/B 题意:在一棵有 n 个节点的树上,有两种操作,一个是把 u 到 v 的路径走一遍,另一个是查询 u 到 f ...
- “景驰科技杯”2018年华南理工大学程序设计竞赛 A. 欧洲爆破(思维+期望+状压DP)
题目链接:https://www.nowcoder.com/acm/contest/94/A 题意:在一个二维平面上有 n 个炸弹,每个炸弹有一个坐标和爆炸半径,引爆它之后在其半径范围内的炸弹也会爆炸 ...
随机推荐
- ajax中 XmlHttp的open( )方法
博客分类: Ajax XML open 创建一个新的http请求,并指定此请求的方法.URL以及验证信息 语法 oXMLHttpRequest.open(bstrMethod, bstrUrl, ...
- Fiddldr 教程之:HTTP协议详解(转)
原文地址:http://www.cnblogs.com/TankXiao/archive/2012/02/13/2342672.html HTTP协议详解 当今web程序的开发技术真是百家争鸣,ASP ...
- React Native开发环境的搭建
我只能说搭建开发环境还是不能相信网上纷乱的博客,还是中文网靠谱. http://reactnative.cn/docs/0.47/getting-started.html 纯粹只是为了记录一下.
- 编写高质量代码改善C#程序的157个建议——建议115:通过HASH来验证文件是否被篡改
建议115:通过HASH来验证文件是否被篡改 MD5算法作为一种最通用的HASH算法,也被广泛用于文件完整性的验证上.文件通过MD5-HASH算法求值,总能得到一个固定长度的MD5值.虽说MD5是一种 ...
- 安卓利用Handlers,AsyncTask和Loaders运行后台程序
安卓的用户界面线程(user interface thread) 1.1 主线程 安卓修改用户界面并从一个单一用户界面线程中处理输入事件,这个线程也被称作主线程(main thread) Androi ...
- Short jhat tutorial: diagnosing OutOfMemoryError by example
转自: http://petermodzelewski.blogspot.com/2013/06/short-jhat-tutorial-diagnosing.html jhat这个工具经过使用, 发 ...
- winsock的io模型(终极篇)
最近在看服务器框架的搭建,看了不少,都是零零碎碎的,觉得看的差不多了,可以写点最后的总结了,然后,竟然发现了这篇文章,总结做的特别好,肯定比我总结写要好多了,所以我也就不写了,直接转吧...... 套 ...
- 在 LINQ to Entities 查询中无法构造实体或复杂类型“Mvc_MusicShop_diy.Models.Order”
错误代码: var orders = db.Orders.Where(o => o.UserId == userid).Select(c => new Order { OrderI ...
- selenium+jenkins+maven+testNG搭建持续集成环境
为了简明起见,分几大部分,很基础的细节就不详述了 一·安装jenkins 二·创建一个maven项目的job 2.1 填上SVN的Repository URL 2.2 由于是在本地执行maven ...
- AJAX方式调用百度天气
后台代码: [HttpPost] public string AjaxWeather() { string CityName = string.IsNullOrEmpty(Request.Form[& ...