NOIP 模拟 929
作者:互联网
匹配
有两个字符串A,B,其中B是A的一个长度为$l_{B}$前缀,现在给B末尾填上字符,求A的最大前缀等于B的后缀
$T<=10,l_{B}<=100000,l_{B}<=l_{A}<=2*l_{B}$,所有字母均为小写字母
题解
考虑到B除了最后一个字符就是A的前缀,所以如果变换后的B不是A的前缀,那么求B的最大前缀等于后缀即可。
用kmp就行了
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=200005; int T,lena,lenb; char c[2],s[maxn],t[maxn]; int fail[maxn]; void kmp(){ fail[0]=fail[1]=0; for(int i=1;i<lenb;i++){ int t=fail[i]; while(t&&s[i]!=s[t]) t=fail[t]; fail[i+1]=(s[i]==s[t] ? t+1 : 0); } } int main(){ freopen("string.in","r",stdin); freopen("string.out","w",stdout); scanf("%d",&T); while(T--){ scanf("%d%d%s%s",&lena,&lenb,s,c); if(s[lenb]==c[0]) {printf("%d\n",lenb+1);continue;} s[lenb++]=c[0]; kmp(); printf("%d\n",fail[lenb]); } }string
回家
有一个n个点m条边的图,求从1到n的必经点。
m<=2n,n<=200000,多组数据
题解
给一种错误思路:考虑必经点一定是割点,必经点一定在最短路上。所以tarjan求出割点之后,跑两遍bfs求最短路,最后判断。
为什么会错呢?因为这些只是性质,并不能推出结论。
最主要的就是不能保证这个割点能使1和n不连通
所以考虑在tarjan的时候记录n是否在子树中,判断即可。
细节在代码注释
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=200005; const int inf=0x3f3f3f; int t,n,m,cur,cnt; int head[maxn]; int dfn[maxn],low[maxn]; int top,sta[maxn]; bool cut[maxn],con[maxn]; int dis[maxn][2]; struct edge{ int x,y,next; }e[maxn<<3]; template<class T>inline void read(T &x){ x=0;int f=0;char ch=getchar(); while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x = f ? -x : x ; } void add(int x,int y){ e[++cnt]=(edge){x,y,head[x]}; head[x]=cnt; } void init(){ cnt=top=cur=0; memset(cut,false,sizeof(cut)); memset(con,false,sizeof(con)); memset(head,0,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); for(int i=1;i<=n;i++) dis[i][0]=dis[i][1]=inf; } void tarjan(int x,int fa){ int num=0;if(x==n) con[x]=true; low[x]=dfn[x]=++cur; for(int i=head[x];i;i=e[i].next){ int y=e[i].y; if(!dfn[y]){ tarjan(y,x); low[x]=min(low[x],low[y]); con[x]|=con[y]; if(dfn[x]<=low[y]&&con[y])//判断con[y]:当因为dfn[x]<=low[y]知道是割点的时候会y的子树分开,如果最后判断x会造成分开的子树不含n cut[x]=true; } else if(y!=fa) low[x]=min(low[x],dfn[y]); } } void solve(){ read(n);read(m); init(); for(int i=1;i<=m;i++){ int x,y; read(x);read(y); if(x==y) continue; add(x,y);add(y,x); } tarjan(1,0); for(int i=2;i<n;i++) if(cut[i]) sta[++top]=i; printf("%d\n",top); for(int i=1;i<=top;i++) printf("%d ",sta[i]); putchar(10); } int main(){ freopen("home.in","r",stdin); freopen("home.out","w",stdout); read(t); while(t--)solve(); } /* 2 4 3 1 2 2 3 3 4 5 5 1 2 2 3 3 4 4 5 4 1 */home
标签:ch,const,前缀,NOIP,int,929,maxn,include,模拟 来源: https://www.cnblogs.com/sto324/p/11620730.html