自用模板

来源:互联网 发布:淘宝网注册用户 编辑:程序博客网 时间:2024/04/28 16:56

字符串

1.环串的最小表示

int getsmall(char s[]){  //以返回值开始的表示为最小串
    int i=0,j=1,k=0;
    while(i<len&&j<len&&k<len){
        int tag=s[(j+k)%len]-s[(i+k)%len];
        if(tag==0){
            k++;
            continue;
        }
        if(tag>0) //表示最大串改不等号
            j+=k+1;
        else
            i+=k+1;
        if(i==j) j++;
        k=0;
    }
    return min(i,j);
}

2.扩展KMP

const int N = 101010;
int next[N],extand[N];
void getnext(char *T){ // next[i]: 以第i位置(下标为i)开始的子串 与 T的公共前缀 
     int i,length = strlen(T);
     next[0] = length;
     for(i = 0;i<length-1 && T[i]==T[i+1]; i++);
          next[1] = i;
          int a = 1;
          for(int k = 2; k < length; k++){
                  int p = a+next[a]-1, L = next[k-a];
                  if( (k-1)+L >= p ){
                       int j = (p-k+1)>0? (p-k+1) : 0; 
                       while(k+j<length && T[k+j]==T[j]) j++;// 枚举(p+1,length) 与(p-k+1,length) 区间比较 
                       next[k] = j, a = k;
                  } 
                  else next[k] = L;
         } 
}
void getextand(char *S,char *T){ //extand[i]: S下标为i开始的串和T的最长公共前缀
   memset(next,0,sizeof(next)); 
         getnext(T); 
         int Slen = strlen(S), Tlen = strlen(T), a = 0;
         int MinLen = Slen>Tlen?Tlen:Slen;
         while(a<MinLen && S[a]==T[a]) a++;
         extand[0] = a, a = 0;
         for(int k = 1; k < Slen; k++){
              int p = a+extand[a]-1, L = next[k-a];  
              if( (k-1)+L >= p ){
                   int j = (p-k+1)>0? (p-k+1) : 0; 
                   while(k+j<Slen && j<Tlen && S[k+j]==T[j] ) j++; 
                   extand[k] = j;a = k; 
              } 
              else extand[k] = L;         
         }
}

3.manacher最长回文串

void manacher(int n){
    p[0]=0;
    int mx=0,id=0;
    for(int i=1;i<n;i++){
        if(mx>i)
            p[i]=min(mx-i,p[2*id-i]);
        else
            p[i]=1;
        while(ss[i+p[i]]==ss[i-p[i]])
            p[i]++;
        if(i+p[i]>mx){
            mx=i+p[i];
            id=i;
        }
    }
}
int main(){
    while(~scanf(" %s",s)){
//预处理
        int len=0;
        ss[len++]='$';
        ss[len++]='#';
        for(int i=0;s[i];i++){
            ss[len++]=s[i];
            ss[len++]='#';
        }
        ss[len]=0;


        manacher(len);//   p[i]-1表示以i为中心的回文串在原串中的长度


        int ans=1;
        for(int i=0;i<len;i++)
            if(p[i]>ans)
                ans=p[i];
        cout<<ans-1<<endl;
    }
}




    原串:   w aa b wsw f d
    新串:   # w # a # a # b# w # s # w # f # d #
辅助数组P:  1 2 1 2 3 2 1 2 1 2 1 4 1 2 1 2 1 2 1


4.Tire

hdu2072

统计一篇文章中不同单词的个数。




const int maxnode=1000010;
struct Tire{
    int ch[maxnode][26];
    int val[maxnode];
    int sz;
    void clear(){
        sz=1;
        memset(ch[0],0,sizeof(ch[0]));
        memset(val,0,sizeof(val));
    }
    int idx(char c){
       return c-'a';
    }
    bool inserts(char s[]){
        int u=0,n=strlen(s);
        for(int i=0;i<n;i++){
            int c=idx(s[i]);
            if(!ch[u][c]){
                memset(ch[sz],0,sizeof(ch[sz]));
                ch[u][c]=sz;
                val[sz]=0;
                sz++;
            }
            u=ch[u][c];
            if(i==n-1){
                bool tag=val[u];
                val[u]=1;
                return tag;
            }
        }
    }
    bool searchs(char s[]){
        int u=0,n=strlen(s);
        for(int i=0;i<n;i++){
            int c=idx(s[i]);
            if(!ch[u][c])
                return false;
            u=ch[u][c];
        }
        return val[u];
    }
};
Tire T;


string s;
char t[5000];
int main()
{
    while(getline(cin,s),s[0]!='#'){
        int ans=0;
        T.clear();
        int len=s.length();
        for(int i=0;i<len;i++){
            int j=0;
            while(s[i]!=32&&s[i]){
                t[j++]=s[i++];
            }
            t[j]=0;
            if(j) ans+=!T.inserts(t);
        }
        printf("%d\n",ans);
    }
    return 0;
}

数学

1.线性筛


//素数线性筛
const int N=1000000;
bool ispri[N+5];
int pri[N],tot=0;
void make(){
    memset(ispri,true,sizeof(ispri));
    for(int i=2;i<N;++i){
        if(ispri[i])
            pri[tot++]=i;
        for(int j=0;j<tot&&i*pri[j]<N;++j){ //遍历当前素数集
            ispri[i*pri[j]]=0;
            if(i%pri[j]==0) //任何一个合数都可以用最小的素数和另一个数的积表示
                break; //若i含质因子pri[j]则i*pri[j+1]可以用另一个数与pri[j]的积筛
        }
    }
    return ;
}




//素数线性筛+欧拉线性筛
void get_prime(){
    phi[1]=1;
    for(int i=2;i<maxn;i++){
        if(!vis[i]){
            prime[num_prime++]=i; //存素数
            f[i]=i; //i的最小质因数为f[i]
            phi[i]=i-1; //i的欧拉值
        }
        for(int j=0;j<num_prime&&i*prime[j]<maxn;j++){
            vis[i*prime[j]]=true;
            f[i*prime[j]]=prime[j];
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];
                    break;
            }
            else
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
}


//求n的所有约数,复杂度为n的约数个数
void dfs(int n,int res){
    if(n==1){
        printf("%d\n",res);
        return ;
    }
    int x = n,t = f[n],cnt = 0; //f[n]为n的最小质因数
    while(x%t==0) x/=t,++cnt;
    dfs(x,res);
    for(int i = 1; i <= cnt; ++i) {
        res = res*t;
        dfs(x,res);
    }
}


0 0
原创粉丝点击