6.29 省选模拟赛 坏题 AC自动机 dp 图论
考场上随手构造了一组数据把自己卡掉了 然后一直都是掉线状态了。
最后发现这个东西不是subtask -1的情况不多 所以就没管无解直接莽 写题有点晚 故没调出来。。
考虑怎么做 容易想到建立AC自动机 然后不能跑到结尾节点 fail是结尾节点的也不能跑。
把那些节点抽出来就可以随便跑了 题目描述非常丧心病狂 两个字符串相等描述的莫名其妙。
不过这道题的本意让我们求出两端在环内的字符串个数。
发现如果存在不是简单环的话是无解的 如果出现两个环的路径上还是环的话也同时无解。
对于前者 一个非常妙的trick是 看这个强联通分量的边数 边数等于点数还是边数大于点数。这个trick 非常的稀有!想了很久都没想到。
对于后者 DAG上的dp也可以顺带求出 对于答案也可以很容易的在DAG上dp求出。
后者这个情况很容易被忽略掉 这里要注意!
code
//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cctype>
#include<cstring>
#include<cmath>
#include<string>
#include<utility>
#include<queue>
#include<vector>
#include<algorithm>
#include<deque>
#include<stack>
#include<list>
#include<bitset>
#include<set>
#include<map>
#define INF 1000000000000000000ll
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define fep(n,p,i) for(int i=n;i>=p;--i)
#define vep(p,n,i) for(int i=p;i<n;++i)
#define db double
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define put(x) printf("%d\n",x)
#define pb push_back
#define ll long long
#define db double
#define putl(x) printf("%lld\n",x)
#define mod 1000000007
#define en(i) t[i].en
#define fail(i) t[i].fail
using namespace std;
char *fs,*ft,buf[1<<15];
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
int x=0,f=1;char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=10010,maxn=2000000;
int n,T,id,cnt,cc,top,len,len1;
char a[MAXN];
int q[MAXN],v[MAXN],f[MAXN],ru[MAXN],num[MAXN];
int dfn[MAXN],c[MAXN],s[MAXN],low[MAXN],g[MAXN],ff[MAXN];
int lin[MAXN],ver[maxn],nex[maxn],lin1[MAXN],ver1[maxn],nex1[maxn];
inline void add(int x,int y){ver[++len]=y;nex[len]=lin[x];lin[x]=len;}
inline void add1(int x,int y){ver1[++len1]=y;nex1[len1]=lin1[x];lin1[x]=len1;}
struct wy{int ch[26];int en,fail;}t[MAXN];
inline void insert(int n)
{
int now=0;
rep(1,n,i)
{
int w=a[i]-'a';
if(!t[now].ch[w])t[now].ch[w]=++id;
now=t[now].ch[w];
}
en(now)=1;
}
inline void build()
{
int l=0,r=0;
rep(0,T,i)if(t[0].ch[i])q[++r]=t[0].ch[i];
while(++l<=r)
{
int x=q[l];
rep(0,T,i)
{
int tn=t[x].ch[i];
if(!tn)t[x].ch[i]=t[fail(x)].ch[i];
else fail(tn)=t[fail(x)].ch[i],q[++r]=tn;
}
}
rep(1,r,i)en(q[i])|=en(fail(q[i]));
}
inline void dfs(int x)
{
dfn[x]=++cnt;low[x]=cnt;s[++top]=x;
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(!dfn[tn])
{
dfs(tn);
low[x]=min(low[x],low[tn]);
}
else if(!c[tn])low[x]=min(low[x],dfn[tn]);
}
if(dfn[x]==low[x])
{
++cc;int y=-1;
while(y!=x)
{
y=s[top--];
c[y]=cc;
++g[cc];
}
}
}
inline void topsort()
{
int l=0,r=0;
rep(1,cc,i)if(!ru[i])q[++r]=i;
int ans=0;
while(++l<=r)
{
int x=q[l];
f[x]+=v[x];if(v[x])ans+=f[x],++ff[x];
if(ff[x]>2){puts("-1");return;}
for(int i=lin1[x];i;i=nex1[i])
{
int tn=ver1[i];
--ru[tn];ff[tn]=max(ff[tn],ff[x]);
f[tn]+=f[x];
if(!ru[tn])q[++r]=tn;
}
}
put(ans);
}
int main()
{
freopen("huai.in","r",stdin);
freopen("huai.out","w",stdout);
gt(T);gt(n);--T;
rep(1,n,i)
{
scanf("%s",a+1);
int len=strlen(a+1),flag=0;
rep(1,len,j)if(a[j]-'a'>T){flag=1;}
if(flag)continue;
insert(len);
}
build();
rep(0,id,i)
{
if(en(i))continue;
rep(0,T,j)
{
int tn=t[i].ch[j];
if(en(tn))continue;
add(i,tn);
//cout<<i<<' '<<tn<<endl;
}
}
dfs(0);
rep(0,id,i)
{
if(en(i))continue;
for(int j=lin[i];j;j=nex[j])
{
int tn=ver[j];
if(c[tn]==c[i]){++num[c[tn]];continue;}
add1(c[tn],c[i]);
}
}
rep(1,cc,i)
{
if(num[i]>g[i]){puts("-1");return 0;}
if(num[i]==g[i])v[i]=1;
}
topsort();//可以反向dfs或者正向topsort.
return 0;
}
6.29 省选模拟赛 坏题 AC自动机 dp 图论的更多相关文章
- 3.29省选模拟赛 除法与取模 dp+组合计数
LINK:除法与取模 鬼题.不过50分很好写.考虑不带除法的时候 其实是一个dp的组合计数. 考虑带除法的时候需要状压一下除法操作. 因为除法操作是不受x的大小影响的 所以要状压这个除法操作. 直接采 ...
- 6.28 NOI模拟赛 好题 状压dp 随机化
算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...
- [CSP-S模拟测试]:密码(AC自动机+DP)
题目传送门(内部题19) 输入格式 第一行两个正整数$n,k$,代表秘钥个数和要求.接下来两个正整数$x$和$y$,意义如题所述.接下来$n$行,每行一个正整数,意义如题所述. 输出格式 一个正整数, ...
- 5.29 省选模拟赛 树的染色 dp 最优性优化
LINK:树的染色 考场上以为这道题要爆蛋了 没想到 推出正解来了. 反正是先写了爆搜的 爆搜最近越写越熟练了 容易想到dp 容易设出状态 f[i][j]表示以i为根的子树内白色的值为j此时黑色的值怎 ...
- 5.29 省选模拟赛 波波老师 SAM 线段树 单调队列 并查集
LINK:波波老师 LINK:同bzoj 1396 识别子串 不过前者要求线性做法 后者可以log过.实际上前者也被我一个log给水过了. 其实不算很水 我自认跑的很快罢了. 都是求经过一个位置的最短 ...
- 5.4 省选模拟赛 修改 线段树优化dp 线段树上二分
LINK:修改 题面就不放了 大致说一下做法.不愧是dls出的题 以前没见过这种类型的 不过还是自己dp的时候写丑了. 从这道题中得到一个结论 dp方程要写的优美一点 不过写的过丑 优化都优化不了. ...
- codehunter 「Adera 6」杯省选模拟赛 网络升级 【树形dp】
直接抄ppt好了--来自lyd 注意只用对根判断是否哟留下儿子 #include<iostream> #include<cstdio> using namespace std; ...
- 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解
今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...
- HDU 4758 Walk Through Squares (2013南京网络赛1011题,AC自动机+DP)
Walk Through Squares Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Oth ...
随机推荐
- 火车运输(最大生成树+lca) 洛谷P1967
货车运输 题目描述 \(A\) 国有 \(n\) 座城市,编号从 \(1\) 到 \(n\) ,城市之间有 \(m\) 条双向道路.每一条道路对车辆都有重量限制,简称限重. 现在有 \(q\) 辆货车 ...
- 二叉树的深度(剑指offer-38)
题目描述 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. 递归解析: 思路: 从根节点出发,查询左子树的深度,获取右子树的深度 ...
- 题解:2018级算法第五次上机 C5-图2
题目描述: 样例: 实现解释: 所有结点对最短路径的板子题 知识点: 寻找所有结点对最短路径,动态规划 坑点: 无坑,注意建边即可 使用的算法为floyd算法 按照程序顺序解释如下: 首先建图,以邻接 ...
- 题解:2018级算法第四次上机 C4-商人卖鱼
题目描述: 样例: 实现解释: 需要简单分析的贪心题 知识点: 贪心,自定义排序,提前存储 题目分析: 卖鱼,鱼卖出去需要时间,鱼没被卖出去之前需要吃饲料 则有,如果卖a鱼的话b鱼会吃饲料c份,而卖b ...
- Python axis的含义
axis=0表述列 axis=1表述行 如下面例子: In [52]: arr=np.arange(12).reshape((3,4))In [53]:arrOut[53]:array([[ 0, 1 ...
- Python之爬虫(二十四) 爬虫与反爬虫大战
爬虫与发爬虫的厮杀,一方为了拿到数据,一方为了防止爬虫拿到数据,谁是最后的赢家? 重新理解爬虫中的一些概念 爬虫:自动获取网站数据的程序反爬虫:使用技术手段防止爬虫程序爬取数据误伤:反爬虫技术将普通用 ...
- 一、Python系列——函数的应用之名片管理系统
card_list = [] def main_desk(): print('*'*50) print('欢迎使用[名片管理系统]V1.0') print('1.新建名片') print('2.显示全 ...
- 【JUnit测试】总结
什么是Junit? Junit是xUnit的一个子集,在c++,paython,java语言中测试框架的名字都不相同 xUnit是一套基于测试驱动开发的测试框架 其中的断言机制:将程序预期的结果与程序 ...
- 深入掌握K8S Pod
k8s系列文章: 什么是K8S K8S configmap介绍 Pod是k8s中最小的调度单元,包含了一个"根容器"和其它用户业务容器. 如果你使用过k8s的话,当然会了解pod的 ...
- springMVC -- 对接UEditor(富文本编辑器)
工作中需要用到UEditor编辑文本,在与springMVC进行整合时,出现了一些问题,结果导致,在进行图片上传时出现如下提示: 上网查询了很多相关资料,此处简要记录下,防止以后遇到类似问题. 一种方 ...