2022/2/10学习总结

昨天整了kmp和hash,今天刷题来了,但过程十分艰难,看明白跟敲出来不是一个量级。

先来一道hash模板试试手 ,先是狠捞的冒泡排序,然后编了个很简单的hash函数,让字符串每一位转int型,完事分别乘不同的数,完事相加,最后取模,然后遍历看看有几个不一样的

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
long long int n,a[10005],max=212370440130137957ll;
char s[10005];
long long int hash();
int main()
{
    scanf("%lld",&n);
    long long int i;
    for(i=0;i<n;i++)
    {
        scanf("%s",s);
        a[i]=hash();
    }
    long long int j,t;
    for(j=0;j<n-1;j++)
    {
        for(i=0;i<n-1-j;i++)
        {
            if(a[i]>a[i+1])
            {
                t=a[i];
                a[i]=a[i+1];
                a[i+1]=t;
            }
        }
    }
    long long int sum=1;
    for(i=0;i<n-1;i++)
    {
        if(a[i]!=a[i+1])
            sum++;

    }
    printf("%lld",sum);
    return 0;
}

long long int hash()
{
    long long int len;
    len=strlen(s);
    long long int i,ss=1,k;
    for(i=0;i<len;i++)
    {
        k=(int)s[i];
        ss=ss*(i+1)*k%max;
    }

    return ss;

}

 接下来这题实在hash模板题后面,结果我一看,这不正好能直接用kmp做吗,完事直接kmp过了。就俩字符串咱给他拼成两个长串,然后去求kmp里的next数组,看看最长的前后缀是多长。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>

int main()
{
    int a[10000],b[10000];
    char s1[10000],s2[10000];
    scanf("%s %s",s1,s2);
    int la=strlen(s1),lb=strlen(s2);
    int i;
    char s3[10000],s4[10000];
    for(i=0;i<la;i++)
    {
        s3[i]=s1[i];
        s4[i+lb]=s1[i];
    }
    for(i=0;i<lb;i++)
    {
        s3[i+la]=s2[i];
        s4[i]=s2[i];
    }
    int j=-1,sum=0;
    a[0]=-1;
    b[0]=-1;
    while(i<la+lb)
    {
        if(j==-1||s3[i]==s3[j])
        {
            i++;j++;
            a[i]=j;
            if(a[i]>sum)sum=a[i];
        }
        else
        {
            j=a[j];
        }
    }
    j=-1;
    i=0;
    while(i<la+lb)
    {
        if(j==-1||s4[i]==s4[j])
        {
            i++;j++;
            b[i]=j;
            if(b[i]>sum)sum=b[i];
        }
        else
        {
            j=b[j];
        }
    }
    printf("%d",sum);
    return 0;
}

字典树,自己想的法子超时了,还是得字典树

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
int n,m;
struct st
{
    char name[100];
    int ha;
}na[20000];
char he[55];

void fast(int left,int right);
int find(int l,int r);

int main()
{
    scanf("%d",&n);
    int i;
    for(i=1;i<=n;i++)
    {
        scanf("%s",na[i].name);
        na[i].ha=0;
    }
    scanf("%d",&m);
    fast(1,n);
    for(i=0;i<m;i++)
    {

        scanf("%s",he);
        int ff;
        ff=find(1,n);
        if(ff==-1)
            printf("WRONG\n");
        else if(na[ff].ha>0)
        {
            printf("REPEAT\n");
        }
        else if(na[ff].ha==0)
        {
            printf("OK\n");
            na[ff].ha=1;
        }
    }
    return 0;
}

void fast(int left,int right)
{

    int l=left,j=right,k;
    char t[100],m[100];
    strcpy(m,na[left].name);
    if(l>j)
        return ;
    while(l<j)
    {
        while(l<j&&(strcmp(na[j].name,m))>=0)j--;
        while(l<j&&(strcmp(na[l].name,m))<=0)l++;
        if(l<j)
        {
            strcpy(t,na[l].name);
            strcpy(na[l].name,na[j].name);
            strcpy(na[j].name,t);
        }
    }
    strcpy(na[left].name,na[l].name);
    strcpy(na[l].name,m);
    fast(left,l-1);
    fast(l+1,right);
}

int find(int l,int r)
{
    int mid=l+(r-1)/2;
    if(strcmp(na[mid].name,he)==0)return mid;
    if(l>r)return -1;
    else if(strcmp(na[mid].name,he)>0)return find(l,mid-1);
    else return find(mid+1,r);
}
//超时我淦
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>

int tree[500001][50];
int ff[500001];
int kk=0;
char s[100];
int n,m;
void goin();
int find();

int main()
{
    scanf("%d",&n);
    int i;
    for(i=0;i<n;i++)
    {
        scanf("%s",s);
        goin();
    }
    scanf("%d",&m);
    for(i=0;i<m;i++)
    {
        scanf("%s",s);
        int f=find();
        if(f==1)
            printf("OK\n");
        else if(f>1)
            printf("REPEAT\n");
        else printf("WRONG\n");
    }
    return 0;
}

void goin()
{
    int k=0,x,len=strlen(s);
    for(x=0;x<len;x++)
    {
        int p;
        p=s[x]-'a';
        if(tree[k][p]==0)
        {

            tree[k][p]=++kk;
        }
        k=tree[k][p];

    }
    ff[k]=1;
}

int find()
{
    int z=0;
    int le=strlen(s);
    int o;
    for(o=0;o<le;o++)
    {
        int y=s[o]-'a';
        if(tree[z][y]==0)
        {
            return 0;
        }
        z=tree[z][y];
    }
    if(ff[z]==2||ff[z]==0)return ff[z];
    ff[z]=2;
    return 1;
}
还是得字典树淦

 

 这题看着简单,做着。。。就硬超时,样例给十万个1和2,传统快排直接快不起来了。重复的数字确实是难搞。只能是整优化的快排了。至于做法,像传统快排那样搞左右指针,一路给他减过去完事,但右指针得弄俩,不然不好办。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
long long n,c,a[300000];
void fast(int l,int r);

int main()
{
    scanf("%lld %lld",&n,&c);
    long long int i;
    for(i=0;i<n;i++){
        scanf("%lld",&a[i]);}
    fast(0,n-1);
    long long int r=0,k=0,l=0,sum=0;
    for(l=0;l<n;l++)
    {
        while(r<n&&a[r]-a[l]<=c)r++;
        while(k<n&&a[k]-a[l]<c)k++;
        sum=sum+r-k;
    }
    printf("%lld",sum);
    return 0;
}

 void fast(int l,int r)
 {
     long long int mid=a[(l+r)/2],t;
     int i=l,j=r;
     do{
        while(a[i]<mid) i++;
        while(a[j]>mid) j--;
        if(i<=j)
        {
            t=a[i];
            a[i]=a[j];
            a[j]=t;
            i++;
            j--;
        }
    }while(i<=j);
    if(l<j) fast(l,j);
    if(i<r) fast(i,r);
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值