【LuoguP4081】[USACO17DEC]Standing Out from the Herd
题意
给定多个字符串,每个串中仅在该串中出现的本质不同的子串个数。
Sol
多串匹配想到用广义SAM。
之后从串的匹配角度不是很好做。发现一个本质不同的串最多只会贡献到一个串的答案里。
那么建完广义SAM后,如果我们能够知道那些点是只有一个串能够到达并且知道是哪个的话我们就可以直接把这个点代表的本质不同的串给贡献到对应串的答案中。
这个很好办,我们在建广义SAM的时候不考虑串之间的匹配,建完后再拿着所有的串重新在广义SAM上跑一遍,当我们遍历到一个点(也就是该串的一个前缀)的时候,它的祖先链上的所有点就都是存在于这个串中的子串,对当前点打上一个标记。如果已有不同标记说明这个点以及它所有的祖先都不会对任何一个串的答案产生贡献,那么直接变成-1表示不对答案产生贡献。
之后我们对 parent 树dfs求出每一个点的状态并且贡献答案就行了。
code:
#include<bits/stdc++.h>
using namespace std;
#define Set(a,b) memset(a,b,sizeof(a))
#define Copy(a,b) memcpy(a,b,sizeof(a))
template<class T>inline void init(T&x){
x=0;char ch=getchar();bool t=0;
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);
if(t) x=-x;return;
}typedef long long ll;
const int N=1e5+10;
const int MAXN=N<<1;
ll ans[N];char S[N];
int son[MAXN][26],pass[MAXN],len[MAXN],length[N],fa[MAXN];
int lst=0,node=0;
struct edge{
int to,next;
}a[N<<1];
int head[N<<1],cnt=0;
inline void add(int x,int y){a[++cnt]=(edge){y,head[x]};head[x]=cnt;}
int n;
void Extend(int c){
if(son[lst][c]&&len[son[lst][c]]==len[lst]+1) lst=son[lst][c];
else {
int p=++node,u=lst;lst=p;len[p]=len[u]+1;
while(~u&&!son[u][c]) son[u][c]=p,u=fa[u];
if(~u) {
int v=son[u][c];
if(len[v]==len[u]+1) return void(fa[p]=v);
int q=++node;Copy(son[q],son[v]);
fa[q]=fa[v];len[q]=len[u]+1;fa[v]=fa[p]=q;
while(~u&&son[u][c]==v) son[u][c]=q,u=fa[u];
}
}return;
}
void Insert(char*s,int L){
lst=0;fa[0]=-1;
for(int i=1;i<=L;++i) Extend(s[i]-'a');
return;
}
void GO(char*s,int id,int L){
int u=0;
for(int i=1;i<=L;++i) {
int c=s[i]-'a';
u=son[u][c];
if(pass[u]>0) pass[u]=-1;
else if(!pass[u]) pass[u]=id;
}
}
void Dfs(int u){
for(int v,i=head[u];i;i=a[i].next) {
v=a[i].to;Dfs(v);
if(~pass[u]) {
if(!pass[u]) pass[u]=pass[v];
else if(pass[u]!=pass[v]) pass[u]=-1;
}
}
if(pass[u]>0) ans[pass[u]]+=len[u]-len[fa[u]];
}
int main()
{
int L=0;init(n);
for(int i=1;i<=n;++i) {
scanf("%s",S+1+L);
length[i]=strlen(S+1+L);
Insert(S+L,length[i]);
L+=length[i];
}
for(int i=1;i<=node;++i) add(fa[i],i);L=0;
for(int i=1;i<=n;++i) GO(S+L,i,length[i]),L+=length[i];
Dfs(0);
for(int i=1;i<=n;++i) printf("%lld\n",ans[i]);
return 0;
}
【LuoguP4081】[USACO17DEC]Standing Out from the Herd的更多相关文章
- 后缀自动机再复习 + [USACO17DEC] Standing Out from the Herd
here:https://oi-wiki.org/string/sam/ 下面转自 KesdiaelKen的雷蒻论坛 来个广义后缀自动机模板题 [USACO17DEC]Standing Out fro ...
- 【[USACO17DEC]Standing Out from the Herd】
题目 不会广义\(SAM\)啊 但信仰插入特殊字符就可以搞定一切了 我们先把所有的串搞在一起建出一个\(SAM\),记得在中间插入特殊字符 对于\(parent\)树上的一个节点,只有当其\(endp ...
- 【LuoguP4081】[SCOI2015]小凸想跑步
题目链接 题意 给你一个凸多边形,求出在其内部选择一个点,这个点与最开始输入的两个点形成的三角形是以该点对凸多边形三角剖分的三角形中面积最小的一个三角形的概率. Sol 答案就是 可行域面积与该凸多边 ...
- P4081 [USACO17DEC]Standing Out from the Herd P
知识点: 广义 SAM 原题面 Luogu 「扯」 随便「口胡」一下居然「过」了. 比较考验「代码能力」,第一次感觉「大模拟」没有白写((( 还有这个「符号」实在是太「上头」了. 前置知识 在线构造广 ...
- P4081 [USACO17DEC]Standing Out from the Herd
思路 对所有串建立广义SAM,之后记录SZ,统计本质不同子串时只统计SZ=1的即可 代码 #include <cstdio> #include <algorithm> #inc ...
- [USACO17DEC]Standing Out from the Herd(广义后缀自动机)
题意 定义一个字符串的「独特值」为只属于该字符串的本质不同的非空子串的个数.如 "amy" 与 “tommy” 两个串,只属于 "amy" 的本质不同的子串为 ...
- [洛谷P4081][USACO17DEC]Standing Out from the Herd
题目大意:给你$n$个字符串,对每个字符串求出只在这个字符串中出现的字串的个数 题解:先建广义$SAM$,然后对每个点统计一下它的子树中是不是都是在同一个字符串中的,是的话,就把这个点标成这一个字符串 ...
- Luogu4081 USACO17DEC Standing Out from the Herd(广义后缀自动机)
建出广义SAM,通过parent树对每个节点求出其是否仅被一个子串包含及被哪个包含. 写了无数个sam板子题一点意思都没啊 #include<bits/stdc++.h> using na ...
- 【BZOJ5137】Standing Out from the Herd(后缀自动机)
[BZOJ5137]Standing Out from the Herd(后缀自动机) 题面 BZOJ 洛谷 题解 构建广义后缀自动机 然后对于每个节点处理一下它的集合就好了 不知道为什么,我如果按照 ...
随机推荐
- 【POJ - 3126】Prime Path(bfs)
Prime Path 原文是English 这里直接上中文了 Descriptions: 给你两个四位的素数a,b.a可以改变某一位上的数字变成c,但只有当c也是四位的素数时才能进行这种改变.请你计算 ...
- [python] 格式化方法 format
先介绍包含的所有规则 花括号声明{}:用于渲染前的参数引用声明,花括号里可以用数字代表引用参数的序号,或者变量名直接引用. 从format参数引入的变量名 冒号: 字符位数声明 空白自动填补符的声明 ...
- 用data的方法获取值的时候,要注意的问题一定要在先封装好
var art=$(".add-more").prev().find(".content").data("list1"); 我们一定要在aj ...
- Java基础(那些习以为常缺不知道原理的地方)
一.基础 1.1 正确的使用equals方法 Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals.如下代码 // 不能使用一个值为null的引用类型变量来调 ...
- 关于redis的几件小事(一)redis的使用目的与问题
1.redis是用来干嘛的? Redis is an open source (BSD licensed), in-memory data structure store, used as a dat ...
- js中new到底做了什么?如何重写new?
new 构造函数()执行顺序1.在堆中开辟对象内存空间, 记为obj2.在obj 中添加__proto__属性并指向 构造函数.prototype3.将构造函数中的this 指向obj4.执行构造函数 ...
- 上传模板到SAP资源库
事物代码:SMW0 -WEB资源库 如果创建后上载本地模板报错,说明没有维护文件类型,需要在导航栏的设置里维护MIME类型添加新的文件后缀名 维护好后再上载模板 ABAP下载模板:以下FORM可以参考 ...
- python中同步、多线程、异步IO、多线程对IO密集型的影响
目录 1.常见并发类型 2.同步版本 3.多线程 4.异步IO 5.多进程 6.总结 1.常见并发类型 I/ O密集型: 蓝色框表示程序执行工作的时间,红色框表示等待I/O操作完成的时间.此图没有按比 ...
- 关于获取某月某日最后一天时Calendar的cal.getActualMaximum(Calendar.DAY_OF_MONTH)的吐槽
例如: 在2017.03.29-31号 新建一个Calendar的単例 设置年:2017 设置月:2 int day = cal.getActualMaximum(Calendar.DAY_OF_MO ...
- CDH5.13.3安装手册
Server端需要打开端口 7180 7182 选址正确的版本,cdh版本不要高于cm版本 CM下载地址 http://archive.cloudera.com/cm5/cm/5/cloudera-m ...