首页 > 其他分享 >cd String

cd String

时间:2024-01-30 15:35:48浏览次数:17  
标签:nxt ch String leq int cd mm ans

动物园(P2375)

题目大意

给一个字符串,定义 \(f_i=max\{x|S_{1...x}=S_{i-x+1...i},x\leq i/2 \}\)
求出每个 \(f_i\) \(n\leq 10^6\)

思路

可以发现 \(f_i\) 的定义类似kmp中的 \(nxt\) 指针,所以我们先利用kmp求出不符合 \(x\leq i/2\) 的 \(f_i\),然后我们可以倍增出小于等于的 \(f_i\) 即可,复杂度 \(O(nlog_n)\)

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+100;
const int mod=1e9+7;
int l,n,nxt[N],num[N];
string s;
void solve()
{
	l=s.length();
	s=' '+s;
	nxt[1]=0;
	num[1]=1;
	int z=0;
	long long ans=1;
	for(int i=2;i<=l;i++)
	{
		while(z!=0&&s[z+1]!=s[i])
		{
			z=nxt[z];
		}
		if(s[z+1]==s[i])
		z++;
		nxt[i]=z;
		num[i]=num[z]+1;
	}
	z=0;
	for(int i=2;i<=l;i++)
	{
		while(z!=0&&s[z+1]!=s[i])
		{
			z=nxt[z];
		}
		if(s[z+1]==s[i])
		z++;
		while(z*2>i)
			z=nxt[z];
		ans*=(num[z]+1);
		ans%=mod;
	}
	cout<<ans<<'\n';
	return;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		solve();
	}
	return 0;
} 

字符串的匹配(BZOJ 1461)

题目大意

定义 \(\{a_i\}\),\(\{b_i\}\) 相同,当且仅当它们离散化之后相同。
给定 \(a_1,...a_n\) 以及 \(b_1,...b_m\),找到所有位置 \(p\) 使得 \(a_p,...a_{p+m-1}\) 和
\(\{b_i\}\) 相同。\(m\leq n\leq 10^5\)

思路

看起来就是kmp,但是我们无法直接知道一个数的排名,所以可以用树状数组或线段树来维护一个数的排名。

#include<bits/stdc++.h>
#define mm 500010
using namespace std;
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
int n,m,k;
int a[mm],b[mm];
int tree[mm<<2];
int rk1[mm],rk2[mm];
int f[mm];
int ans[mm],Ans;
int lowbit(int x){return x&(-x);}
void add(int x,int y)
{
    for(int i=x;i<=k;i+=lowbit(i))
        tree[i]+=y;
}
int get(int x)
{
    int ans=0;
    for(int i=x;i>0;i-=lowbit(i))
        ans+=tree[i];
    return ans;
}
int main()
{
    n=read(),m=read(),k=read();
    for(int i=0;i<n;i++)
        a[i]=read();
    for(int i=0;i<m;i++)
        b[i]=read(),add(b[i],1),rk1[i]=get(b[i]-1),rk2[i]=get(b[i]);
    memset(tree,0,sizeof(tree));
    int j=0;
    for(int i=1;i<m;i++)
    {
        add(b[i],1);
        j=f[i];
        while(j && (rk1[i]!=get(b[j]-1) || rk2[i]!=get(b[j])))
        {
            for(int k=i-j;k<i-f[j];k++)
                add(b[k],-1);
            j=f[j];
        }
        if(rk1[j]==get(b[i]-1) && rk2[j]==get(b[i]))
            f[i+1]=j+1;
        else
            f[i+1]=0;
    }
    j=0;
    memset(tree,0,sizeof(tree));
    for(int i=0;i<n;i++)
    {
        add(a[i],1);
        while(j && (rk1[j]!=get(a[i]-1) || rk2[j]!=get(a[i])))
        {
            for(int k=i-j;k<i-f[j];k++)
                add(a[k],-1);
            j=f[j];
        }
        if(rk1[j]==get(a[i]-1) && rk2[j]==get(a[i]))
            ++j;
        if(j==m)
        {
            ans[++Ans]=i-j+1;
            for(int k=i-j+1;k<=i;k++)
                add(a[k],-1);
            j=0;
        }
    }
    printf("%d\n",Ans);
    for(int i=1;i<=Ans;i++)
        printf("%d\n",ans[i]+1);
    return 0;
}

SZA-Template(P3426)

题目大意

Byteasar 想在墙上涂一段很长的字符, 他为了做这件事从字符的前面一段中截取了一段作为模版。然后将模版重复喷涂到相应的位置后就得到了他想要的字符序列。一个字符可以被喷涂很多次, 但是一个位置不能喷涂不同的字符。做一个模版很费工夫, 所以他想要模版的长度尽量小,求最小长度是多少 \(n\leq 10^6\)

题目大意

首先能发现这个一定是这个字符串的 \(border\),并且知道长度大于 \(|s|/2\) 的 \(border\) 一定都为等差数列,且一个字符串的所有 \(border\) 就是kmp中\(nxt\)。

#include<bits/stdc++.h>
#define rint register int
#define mm 500010
int n,nxt[mm],h[mm];
int f[mm];
char s[mm];
int main()
{
    scanf("%s",s+1);
    n=strlen(s+1);
    nxt[0]=-1,f[1]=1,h[1]=1;
    for(rint i=2,j=0;i<=n;++i)
    {
        while(j!=-1 && s[j+1]!=s[i])
            j=nxt[j];
        nxt[i]=++j;
    }
    for(rint i=2;i<=n;++i)
    {
        f[i]=i;
        if(h[f[nxt[i]]]>=i-nxt[i])
            f[i]=f[nxt[i]];
        h[f[i]]=i;
    }
    printf("%d\n",f[n]);
    return 0;
}

Country(BZOJ 2061)

题目大意

有 \(n\leq26\) 个字符串变量,它们可以包含其他的字符串变量,也可以包含小写字母(这些变量用大写字母表示)。
举个栗子:A=greatglorycorrect,B=xx,C=leadusgo,D=ABC,E=DDDDdjh ,F=EEEEEgoodbye,数据保证定义是无环的。

给定一个小写字母组成的模式串,求某一个变量所代表的字符串里这个模式串出现了几次。模式串长度, 每条描述的长度 \(\leq 100\)

思路

很明显我们要把所有的大写字母改成小写字母,但暴力改肯定不行,尝试优化这个暴力,也就是记忆化搜索,对于每个大写字母,我们递归下去,对于一串小写字母,我们直接kmp查找即可。

#include<bits/stdc++.h>
#define mm 110
#define mod 10000
using namespace std;
int n,s;
int a[mm][mm];
char b[mm];
char t[mm];
int len[mm],lenb;
int nxt[mm];
void KMP()
{
    for(int i=2,j=0;i<=lenb;i++)
    {
        while(j && b[i]!=b[j+1])
            j=nxt[j];
        if(b[i]==b[j+1])
            ++j;
        nxt[i]=j;
    }
}
int dp[mm][mm];
int pos[mm][mm];
int dfs(int x,int y)
{
    if(dp[x][y]!=-1)
        return dp[x][y];
    dp[x][y]=0;
    int j=y;
    for(int i=1;i<=len[x];i++)
    {
        if(a[x][i]>='A' && a[x][i]<='Z')
        {
            int id=a[x][i]-'A'+1;
            dp[x][y]+=dfs(id,j);
            dp[x][y]%=mod;
            j=pos[id][j];
        }
        else
        {
            int p=j;
            while(p && b[p+1]!=a[x][i])
                p=nxt[p];
            if(b[p+1]==a[x][i])
                ++p;
            j=p;
            if(j==lenb)
            {
                ++dp[x][y];
                dp[x][y]%=mod;
            }
        }
    }
    pos[x][y]=j;
    return dp[x][y];
}
int main()
{
    cin>>n>>t[0];
    s=t[0]-'A'+1;
    for(int i=1;i<=n;i++)
    {
        cin>>t+1;
        int Len=strlen(t+1);
        for(int j=3;j<=Len;j++)
            a[t[1]-'A'+1][j-2]=t[j];
        len[i]=Len-2;
    }
    cin>>b+1;
    lenb=strlen(b+1);
    KMP();
    memset(dp,-1,sizeof(dp));
    dfs(s,0);
    printf("%d\n",dp[s][0]);
    return 0;
}

Substrings in a String(CF914F)

题目大意

单点修改,每次问一个串 \(T_i\) 在 \(S[l,r]\) 中的出现次数。\(n,q,\sum{|T_i|\leq 10^5}\)

思路

看起来像一个字符串科技题,但标签打了二进制,可以用 \(bitset\),我们用 \(ans\) 存下所有可能的左端点,当处理第 \(i\) 个字符时,\(res\&=(b[c[i]]>>(i-1))\) 即可,其中 \(c\) 为待匹配字符串,最终的 \(res\) 就是匹配的所有左端点,然后我们求出合法区间内 \(ans\) 中 \(1\) 的个数即可。

#include<bits/stdc++.h>
#define mm 100010
using namespace std;
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
bitset<mm> a[256],res;
char s[mm],t[mm];
int Q,lens;
int main()
{
    scanf("%s",s+1);
    lens=strlen(s+1);
    for(int i=1;i<=lens;i++)
        a[s[i]][i]=1;
    Q=read();
    while(Q--)
    {
        int op=read();
        if(op==1)
        {
            int x=read();
            scanf("%s",t+1);
            int lent=strlen(t+1);
            a[s[x]][x]=0;
            a[t[1]][x]=1;
            s[x]=t[1];
        }
        else
        {
            int l=read(),r=read();
            scanf("%s",t+1);
            int lent=strlen(t+1);
            res.set();
            for(int i=1;i<=lent;i++)
                res&=(a[t[i]]>>(i-1));
            int l_ans=(res>>l).count();
            int r_ans=(res>>(r-lent+2)).count();
            printf("%d\n",max(0,l_ans-r_ans));
        }
    }
    return 0;
}

标签:nxt,ch,String,leq,int,cd,mm,ans
From: https://www.cnblogs.com/noipwen/p/17997220

相关文章

  • cd graph
    图论专场Fairy(CF19E)题目大意给出一张无向图,求删除一条边后此图变成二分图的所有删边种类\((n\leq10^4)\)。思路虽然看起来\(O(n^2)\)能过,但其实是过不了的,我们知道,判断二分图的一种方式是判断有无奇环,所以问题变成了删去一条边后图中有无奇环,如果有环重合,可以用类似异或......
  • cd 数论
    数论专场StrangeLimit题目大意给你\(p\)和\(m\),求\(p^{p^{p^{p……}}}\mod\m!\)思路有\(n\)个\(p\),\(n\)为无穷大,也就是递归里套一个指数循环节,然后因为\(n\)趋向于无限大,那么当前要\(mod\)的\(x\)\(\mu(\mu(\mu(m)))\),也在一直缩小。如果当\(p\mo......
  • cd 游记
    Day1差不多晚上才到,去吃了火锅,菜里都有花椒,晚上在寝室整理自己的东西,了解了一下制度。Day2上午先做了一下昨天的题目,难度还行,补了\(Ice-creamTycoon\)和\(NewYearandConference\),下午是金天讲课,知道了许多有意思的DS转换,难度为单峰。中午和yjf和hhx去外面吃饭,吃的云吞,......
  • etcd v2 版本数据备份恢复脚本
    importrequestsimportjsonimportsysaction=sys.argv[1]etcdaddr=sys.argv[2]defbackup_data():url=f"{etcdaddr}/v2/keys/?recursive=true"response=requests.get(url)ifresponse.status_code==200:data=res......
  • Walrus 实用教程|Walrus + Gitlab,打通CI/CD 自动化交付!
    Walrusfile是Walrus0.5版本推出的新功能,用户可以通过一个非常简洁的YAML描述应用或基础设施资源的部署配置,然后通过WalrusCLI执行walrusapply或在WalrusUI上进行import,将Walrusfile提交给Walrusserver,由Walrusserver完成对应用或基础设施资源的部署/配置/......
  • 出大招了,这个顶级 CI/CD 产品,最近甩出了两个“王炸”
    极狐GitLabCI自16.0版本以来,陆续引入了CI/CDcomponent和CI/CDCatalog两个重量级功能,提高了CI/CD流水线的复用性,从此编写流水线可能像搭积木那样便捷了。计算机中的所有问题都可以通过增加一个间接层来解决。——DavidWheeler(大卫·惠勒)编写CI/CD流水线是DevO......
  • PCDN 流量盒子 系统定制 OEM看过来
    赋能每个家庭,闲置带宽流量可以变成收益的PCDN机顶盒,各位听说过吗?PCDN是一种高效的内容分发网络,它通过负载均衡、数据优化、网络优化等技术,提高网站的可用性、稳定性和性能。PCDNOEM,电话/微信:13540308877我们专注于使用自主可控的核心技术构建跨越“云-边-端”的全栈边缘计算,......
  • Gogs,支付宝沙箱支付,DevOps&CI/CD
    1.Gogs2.支付宝沙箱支付测试3.DevOps是生么4.CI/CD是什么1.Gogs是一款极易搭建的自助Git服务。Gogs的目标是打造一个最简单、最快速和最轻松的方式搭建自助Git服务。使用Go语言开发使得Gogs能够通过独立的二进制分发,并且支持Go语言支持的所有平台,包括Linux、Ma......
  • 第二届数字化经济与管理科学国际学术会议(CDEMS 2024)
    【经济&管理|录用率高】第二届数字化经济与管理科学国际学术会议(CDEMS2024)20242nd InternationalConferenceonDigitalEconomyandManagementScience(CDEMS2024) 重要信息 大会官网:www.icdems.com 大会时间:2024年4月26-28日大会地点:武汉(线上线下结合)✱截稿日期:20......
  • UOJ #33 树上 GCD
    套路地,对每个\(g\in[1,n-1]\)求出有多少对无序对\((u,v)\)满足\(g|f(u,v)\),然后就可以用一个倒序枚举的\(\mathcalO(n\logn)\)的容斥求出答案。考虑点分治,对每个经过分治中心\(c\)的\(u\rightsquigarrow\text{lca}(u,v)\rightsquigarrowv\)只需分两种......