zoukankan      html  css  js  c++  java
  • ACM大一寒假集训1.3

    【模板】后缀排序

    看这篇学的,觉得讲的挺好后缀数组算法总结

    char s[maxn];
    int sa[maxn],x[maxn],y[maxn],c[maxn],n;
    void build(int m)
    {
        int i;
        for(i=0;i<m;i++) c[i]=0;
        for(i=0;i<n;i++) c[x[i]=s[i]]++;
        for(i=1;i<m;i++) c[i] += c[i-1];
        for(i=n-1;i>=0;i--) 
          sa[--c[x[i]]]=i;
    	// for (int i=0;i<n;i++) cout<<sa[i]<<endl;
        for(int k=1;k<n;k<<=1) 
        {   //倍增,将k凑成k*2长度,k>=n就没必要了
            int p=0;
            for(i=n-1;i>=n-k;i--) y[p++]=i;
            for(i=0;i<n;i++) 
              if(sa[i]>=k) y[p++]=sa[i]-k;//sa[i]>=k的位置才能做第二关键字
    		
            for(i=0;i<m;i++) c[i]=0;
            for(i=0;i<n;i++) c[x[y[i]]]++;
            for(i=1;i<m;i++) c[i]+=c[i-1];
            for(i=n-1;i>=0;i--) 
              sa[--c[x[y[i]]]]=y[i];//两次排序后的数组
    		//下标是排名,值为首字母位置:sa,y
    		//下标是位置,值是排名:x
            swap(x,y);//y:第一关键字排序   x:上一轮的rank
            p=1;x[sa[0]]=0;
            for(i=1;i<n;i++)
              if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])
                x[sa[i]]=p-1;
              else x[sa[i]]=p++;
            if(p>=n) break;
            m=p;  
        }
        return ;
    }
    
    int main()
    {
        scanf("%s",s);
        n=strlen(s);
        build(10000);
        for (int i=0;i<n;i++)
        cout<<sa[i]+1<<" ";
        return 0;
    }
    

    难度:3

    T1洛谷P2870 [USACO07DEC]Best Cow Line G

    明显的贪心是:比较首字符和尾字符的大小,取小的。

    但对于大小相同的就不好判断了,我们用f[i]表示从ii开始的后缀,用g[i]表示从ii开始的前缀。那么遇到str[L]=str[R]时,比较f[L]和g[R]即可,这个可以用后缀数组排序实现。

    难度:3

    T2P4051 [JSOI2007]字符加密

    把字符串首尾相接,扩展为原来的两倍,就能按后缀数组的方法处理

    难度:3

    矩阵快速幂模板

    #include<bits/stdc++.h> 
    using namespace std;
    long long mod=1000000007,n,k;
    struct node
    {
    	long long m[200][200];
    }a;
    node x(node a,node b)
    {
    	node t;
    	for (int i=0;i<n;i++)
    		for (int j=0;j<n;j++)
    		{
    			t.m[i][j]=0;
    			for (int k=0;k<n;k++)
    			t.m[i][j]=(t.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
    		}
    	return t;
    }
    node ksm(node a,long long k)
    {
    	node ret=a,b=a;k--;
    	while (k>0)
    	{
    		if (k%2==1)
    		ret=x(b,ret);
    		b=x(b,b);
    		k=k/2;
    	}
    	return ret;
    }
    int main()
    {
    	scanf("%lld%lld",&n,&k);
    	for (int i=0;i<n;i++)
    		for (int j=0;j<n;j++)
    		scanf("%lld",&a.m[i][j]);
    		a=ksm(a,k);
    	for (int i=0;i<n;i++)
    	{
    		for (int j=0;j<n;j++)
    		printf("%lld ",a.m[i][j]);
            printf("
    ");
    	}
    	return 0;
    }
    
    

    T3P1962 斐波那契数列

    构造矩阵base=image-20210203023715427

    初始矩阵ans=image-20210203023802502

    Fn为ans*base^(n-2),用矩阵快速幂即可

    难度:2

    广义斐波那契数列是更一般的形式)

    T4矩阵加速(数列)

    和上一题差不多,构造个矩阵就行了

    难度:2

    矩阵经典问题有向图的可达矩阵

    例题:HDU2167

    难度:3

  • 相关阅读:
    2020软件工程作业00
    2020软件工程作业03
    2020软件工程作业02
    软件工程作业01
    2020软件工程作业06
    2020软件工程作业05
    问题清单
    2020软件工程作业04
    2020软件工程作业02
    2020软件工程作业1
  • 原文地址:https://www.cnblogs.com/71-111/p/14365063.html
Copyright © 2011-2022 走看看