一本通 提高篇—字典树

文章目录

    • #10049. 「一本通 2.3 例 1」Phone List
    • 10050. 「一本通 2.3 例 2」The XOR Largest Pair
    • #10051. 「一本通 2.3 例 3」Nikitosh 和异或
    • #10052. 「一本通 2.3 练习 1」Immediate Decodability
    • #10053. 「一本通 2.3 练习 2」L 语言
    • #10054. 「一本通 2.3 练习 3」Secret Message 秘密信息
    • #2012. 「SCOI2016」背单词
    • #10056. 「一本通 2.3 练习 5」The XOR-longest Path

#10049. 「一本通 2.3 例 1」Phone List

一本通 提高篇—字典树_第1张图片
代码

#include "stdio.h"
#include "string.h"
const int N=1e5+5,Z=11;
int a[N][Z],sum;
//数组不要开太大,初始化也要时间,会超时,说出来都是泪
char s[99];
bool b[N];
void clear()
{
	memset(a,0,sizeof(a));
	memset(b,false,sizeof(b));
}
bool ppp(char *s)
{
	int u=1;
	bool zui=false;
	int l=strlen(s);
	for(int i=0;i<l;i++)//i
	{
		int c=s[i]-'0';
		if(!a[u][c])
			a[u][c]=++sum;	
		else if(i==l-1)
			zui=true;	//这个字符串为前缀 
		u=a[u][c];
		if(b[u])//是否遇到前面字符串结尾 ,寻找前缀 
			zui=true;
	}
	b[u]=true;//现在这个字符串的结尾标记;
	return zui; 
 } 
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		sum=1;
		clear();
		scanf("%d",&n);
		bool ans=false;
		for(int i=0;i<n;i++)
		{
			scanf("%s",s);
			if(!ans)
			ans=ppp(s); 
		}
		if(ans)
			printf("NO\n");
		else
			printf("YES\n");
	}
} 

10050. 「一本通 2.3 例 2」The XOR Largest Pair

一本通 提高篇—字典树_第2张图片
代码

#include "stdio.h"
#include "algorithm"
#include "string.h" 
#include  "math.h"
using namespace std;
int a[9000099][2],b[100099];
int sum=1;
void ppp(int x)
{
	int u=1;
	//二进制,1<<30:把1向前移30位
	//i>>1,后移一位
	for(int i=1<<30;i;i>>=1)//或for(int i=1<<30;i>=1;i>>=1)
	{
		int v=(i&x)?1:0;
		if(a[u][v])
			u=a[u][v];
		else
		{
			a[u][v]=++sum;
			u=a[u][v];
		} 
	}
}
int find(int x)
{
	int u=1,s=0;
	for(int i=1<<30;i>=1;i>>=1)
	{
		int v=(i&x)?0:1;
		if(a[u][v])
		{
			u=a[u][v];
				s+=i;//v=0时,x此位置等于1 
				//v=1时,x此位置等于1,故s+=i
		}
		else
			u=a[u][1-v];
	}
	return s;
}
int main()
{
	int i,k;
	scanf("%d",&k);
	for(i=0;i<k;i++)
	{
		scanf("%d",&b[i]);
		ppp(b[i]);
	}
	int ans=0;
	for(i=0;i<k;i++)
		ans=max(ans,find(b[i]));
	printf("%d\n",ans);
	
	
	 
}

#10051. 「一本通 2.3 例 3」Nikitosh 和异或

一本通 提高篇—字典树_第3张图片

代码

#include "stdio.h"
#include "algorithm"
#include "string.h"
#include "math.h"
using namespace std;
int a[9990099][2], b[400099], l[400099], r[400099];
int tot;
void ppp(int x) {
    int u = 1;

    for (int i = 1 << 30; i; i >>= 1) { //不知为什么写成 for(int i=1<<30;;i>>=1)不对
  
        int v = (i & x) ? 1 : 0;

        if (a[u][v])
            u = a[u][v];
        else {
            a[u][v] = ++tot;
            u = a[u][v];
        }
    }
}
int find(int x) {
    int u = 1, s = 0;

    for (int i = 1 << 30; i > 0; i >>= 1) {
        int v = (i & x) ? 0 : 1;

        if (a[u][v]) {
            u = a[u][v];
            s += i;
        } else
            u = a[u][1 - v];
    }

    return s;
}
int main() {
    tot = 1;
    int i, n, k = 0;
    scanf("%d", &n);
    ppp(0);
//如果1到n-5的异或为最大值,那么k=b[1]^b[2]^……^b[n-5]
//在find()函数中如何才能得到了,find(k)=k^0;故先把0加进去
    for (i = 1; i <= n; i++) {
        scanf("%d", &b[i]);
        k ^= b[i];
        ppp(k);
        l[i] = max(l[i - 1], find(k));
    }

    tot = 1;
    memset(a, 0, sizeof(a));
    ppp(0);

    for (i = n; i >= 1; i--) {
        k ^= b[i];
        ppp(k);
        r[i] = max(r[i + 1], find(k));
    }

    int ans = 0;

    for (i = 1; i < n; i++)
        ans = max(ans, l[i] + r[i + 1]);

    printf("%d\n", ans);
}

#10052. 「一本通 2.3 练习 1」Immediate Decodability

一本通 提高篇—字典树_第4张图片
代码

#include "stdio.h"
#include "string.h"
int a[99999][10];
int book[99999];
char c[13];
int n = 0;
int tot = 1, k = 0;
int ppp(char c[13]) {
    int l = strlen(c);
    int u = 1, y = 0;

    for (int i = 0; i < l; i++) {
        int v = c[i] - '0';

        if (!a[u][v])
            a[u][v] = ++tot;
        else if (a[u][v] && i == l - 1)
            y = 1;

        u = a[u][v];

        if (book[u])
            y = 1;
    }

    book[u] = 1;
    return y;
}
int main() {
    while (~scanf("%s", c)) {
        if (c[0] == '9') {
            memset(a, 0, sizeof(a));
            memset(book, 0, sizeof(book));
            n++;
            tot = 1;

            if (k)
                printf("Set %d is not immediately decodable\n", n);
            else
                printf("Set %d is immediately decodable\n", n);

            k = 0;
        }

        if (ppp(c))
            k = 1;
    }
}

#10053. 「一本通 2.3 练习 2」L 语言

一本通 提高篇—字典树_第5张图片
代码

#include "stdio.h"
#include "algorithm"
#include "string.h"
using namespace std;
int a[11911111][30];
int b[11911111];
char c[999999];
int ll[999999];
int tot = 1, l;
void ppp() {
    int u = 1;
    int lll = strlen(c);

    for (int i = 0; i < lll; i++) {
        int t = c[i] - 'a' + 1;

        if (a[u][t])
            u = a[u][t];
        else {
            a[u][t] = ++tot;
            u = a[u][t];
        }
    }

    b[u] = 1;
}
void find(int i) {
    int u = 1;

    for (i; i < l; i++) {
        int t = c[i] - 'a' + 1;

        if (a[u][t])
            u = a[u][t];
        else
            break;

        if (b[u])
            ll[i + 1] = 1;
    }
}
int main() {
    int n, m;
    scanf("%d%d", &n, &m);

    for (int i = 0; i < n; i++) {
        scanf("%s", c);
        ppp();
    }

    for (int i = 0; i < m; i++) {
        memset(ll, 0, sizeof(ll));
        scanf("%s", c);
        l = strlen(c);
        ll[0] = 1;

        for (int j = 0; j < l; j++) {
            if (ll[j])
                find(j);
        }

        for (int j = l; j >= 0; j--) {
            if (ll[j]) {
                printf("%d\n", j);
                break;
            }
        }
    }
}

#10054. 「一本通 2.3 练习 3」Secret Message 秘密信息

一本通 提高篇—字典树_第6张图片
代码

#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;
int a[11111111][12];
int b[11111111];
int s[11111111];
char c[111111];
int l, tot = 1;
void ppp() {
    int u = 1;

    for (int i = 0; i < l; i++) {
        int v = c[i] - '0';

        if (!a[u][v])
            a[u][v] = ++tot;

        u = a[u][v];
        s[u]++;
    }

    b[u]++;

}
int find() {
    int i, u = 1, k = 0;

    for (i = 0; i < l; i++) {
        int v = c[i] - '0';

        if (a[u][v])
            u = a[u][v];
        else
            break;

        if (i != l - 1 && b[u])
            k += b[u];
    }

    if (i == l)
        k += s[u];

    return k;
}
int main() {
    int n, m, z, j;
    scanf("%d%d", &n, &m);

    for (int i = 0; i < n; i++) {
        scanf("%d", &l);

        for (j = 0; j < l; j++) {
            scanf("%d", &z);
            c[j] = z + '0';
        }

        c[j] = '\0';
        ppp();
    }

    for (int i = 0; i < m; i++) {
        scanf("%d", &l);

        for (j = 0; j < l; j++) {
            scanf("%d", &z);
            c[j] = z + '0';
        }

        c[j] = '\0';
        int sum = find();
        printf("%d\n", sum);
    }
}

#2012. 「SCOI2016」背单词

没写

#10056. 「一本通 2.3 练习 5」The XOR-longest Path

没写

你可能感兴趣的:(字符串算法,c语言,c++)