BZOJ 4032 trie树+各种乱搞

思路 :

先对b 的所有后缀建立trie树

第一问

暴力枚举a串的起点

在trie树上跑 找到最短的

第二问

也是暴力枚举a串的起点

a和b顺着暴力匹配就好

第三问

求出来a在第i个位置 加一个字母j 能够到的最近的位置 f[i][j] 到最后就是inf

从f[0][j]DFS 在trie上跟着跑找到最小的deep更新答案

第四问

先按照求f一样同理求出b串 的  g

dp[i][j]表示a的前i个位置 b不得不匹配到b的第j个位置

            dp[i+1][j]=min(dp[i+1][j],dp[i][j]),

            dp[i+1][g[j][a[i]]]=min(dp[i+1][g[j][a[i]]],dp[i][j]+1);

1—>strlen(a)+1 min dp[i][inf]就是答案

这题看起来简单  其实感觉在考场根本写不出来...

//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=2050,inf=2010;
int ch[N*N/2][27],f[N][27],g[N][27],dp[N][N],cnt,ans1,ans2,ans3,ans4,vis[27];
void insert(char *a){
    int now=0;
    for(int i=0;a[i];i++){
        if(!ch[now][a[i]])ch[now][a[i]]=++cnt;
        now=ch[now][a[i]];
    }
}
int solve1(char *a){
    int now=0,i;
    for(i=0;a[i];i++){
        if(!ch[now][a[i]])return i+1;
        else now=ch[now][a[i]];
    }return inf;
}
void solve3(int x,int now,int deep){
    if(x==inf)return;
    if(!now&&deep){ans3=min(ans3,deep);return;}
    for(int i=1;i<=26;i++)solve3(f[x][i],ch[now][i],deep+1);
}
char a[N],b[N];
int main(){
    scanf("%s%s",a+1,b+1);
    int n1=strlen(a+1),n2=strlen(b+1);
    for(int i=1;i<=n1;i++)a[i]=a[i]-‘a‘+1;
    for(int i=1;i<=n2;i++)b[i]=b[i]-‘a‘+1;
    for(int i=1;i<=n2;i++)insert(b+i);
    ans1=ans2=ans3=ans4=inf;
    for(int i=1;i<=n1;i++)ans1=min(ans1,solve1(a+i));
    for(int i=1;i<=n1;i++){
        int now=1;
        for(int j=0;i+j<=n1;now++,j++){
            while(a[i+j]!=b[now]&&now<=n2)now++;
            if(now>n2){ans2=min(ans2,j+1);break;}
        }
    }
    for(int i=0;i<=n1;i++){
        memset(vis,0,sizeof(vis));
        for(int j=i+1;j<=n1;j++)if(!vis[a[j]])vis[a[j]]=j;
        for(int j=1;j<=26;j++)f[i][j]=vis[j]?vis[j]:inf;
    }solve3(0,0,0);
    for(int i=0;i<=n2;i++){
        memset(vis,0,sizeof(vis));
        for(int j=i+1;j<=n2;j++)if(!vis[b[j]])vis[b[j]]=j;
        for(int j=1;j<=26;j++)g[i][j]=vis[j]?vis[j]:inf;
    }
    memset(dp,0x3f,sizeof(dp)),dp[0][0]=0;
    for(int i=0;i<=n1;i++)
        for(int j=0;j<=n2;j++)
            dp[i+1][j]=min(dp[i+1][j],dp[i][j]),
            dp[i+1][g[j][a[i]]]=min(dp[i+1][g[j][a[i]]],dp[i][j]+1);
    for(int i=1;i<=n1+1;i++)ans4=min(ans4,dp[i][inf]);
    printf("%d\n%d\n%d\n%d\n",ans1==inf?-1:ans1,ans2==inf?-1:ans2,ans3==inf?-1:ans3,ans4==inf?-1:ans4);
}
时间: 2024-08-04 02:50:53

BZOJ 4032 trie树+各种乱搞的相关文章

BZOJ 1811 IOI 2005 mea 乱搞

题目大意:给出一个序列中相邻两个的平均值,问有多少个序列可以满足这个性质. 思路:不难看出,只要确定了任意一个数字,整个序列就是确定的.我们设第一个值为k,那么后面的值都可以用表达式表示.然后做一下差分,保证每一项>0,就可以确定k的范围,每一个k值对应一个序列. CODE: #define _CRT_SECURE_NO_DEPRECATE #include <cmath> #include <cstdio> #include <cstring> #include

bzoj 4900 [CTSC2017]密钥 模拟+乱搞

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4900 1 #include<cstring> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdio> 6 #include<vector> 7 8 #define N 40000007 9 #define FOR(a,b,c)

【BZOJ-4523】路由表 Trie树 + 乱搞

4523: [Cqoi2016]路由表 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 155  Solved: 98[Submit][Status][Discuss] Description 路由表查找是路由器在转发IP报文时的重要环节.通常路由表中的表项由目的地址.掩码.下一跳(Next Hop)地址和其他辅助信息组成.例如: 当路由器收到一个IP报文时,会将报文中的目的IP地址与路由表中的表项逐条进行比较,选择匹配且最明确的表项,将报文转发给

BZOJ 2741【FOTILE模拟赛】L 分块+可持久化Trie树

题目大意 给出一个序列,求[l, r]中的最大连续xor 和. 强制在线 思路 先把整个序列分成n  √  块,预处理每一块的开头到每个数字的最大连续xor 和.这个我们只需处理出前缀xor 和,之后用可持久化Trie树就可以搞定.这样询问的右边就是整块的了.剩下左边的随便暴力一下就能过了.. CODE #define _CRT_SECURE_NO_WARNINGS #include <cmath> #include <cstdio> #include <cstring>

BZOJ 3012 [Usaco2012 Dec]First! wzq脑洞hash树(正解trie树)

博客风格转化计划实验篇2 题意: 给n(n<=30000)个字符串,所有字符串长度加起来不超过300000(字符串只含有小写字母). 求解哪些字符串可以称作第一字符串. 一个字符串能被称为第一字符串的条件为存在一种字典序使它排在第一名. 方法: wzq脑洞hash树-.. 然而并没有trie树优越. 并且我脑洞的这个树好处有啥:暂且不知道. 坏处有啥:很容易被卡,自带常数. 所以为什么要这么写?只是因为我跟wjc说这题我特么一定要用带hash的东西搞过去! *目标达成√ 解析: 对于以下内容,请

BZOJ 1212 HNOI 2004 L语言 Trie树

题目大意:给出一些单词,和一些句子,当且仅当句子可以分割成的子串都可以被词典翻译,就说明这个子串是可以被翻译的.求最长的可以被翻译的前缀长度. 思路:利用Trie树来刷数组,能够刷到的最长的地方就是这个串最长可以翻译到的地方. PS:在BZOJ上Trie居然比AC自动机快,我的渣代码都刷到第一篇了... CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorith

【51nod1443】路径和树(堆优化dijkstra乱搞)

点此看题面 大致题意:给你一个无向联通图,要求你求出这张图中从u开始的权值和最小的最短路径树的权值之和. 什么是最短路径树? 从\(u\)开始到任意点的最短路径与在原图中相比不变. 题解 既然要求最短路径,那么最容易想到的就是\(dijkstra\)和\(SPFA\)(毕竟Floyd的时间复杂度难以承受),又由于黄学长说能用\(dijkstra\)时尽量用\(dijkstra\),所以,我就打了一个堆优化的\(dijkstra\)开始乱搞. 其实,这道题目的思路真的挺简单的,只要朴素地做一遍\(

【BZOJ 4148】 4148: [AMPPZ2014]Pillars (乱搞)

4148: [AMPPZ2014]Pillars Time Limit: 5 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 100  Solved: 49 Description 给定一个n*m的矩形,其中有f个2*2的障碍物,其中任意两个障碍物中心之间的欧几里得距离至少为6, 且每个障碍物的中心到边缘的距离至少为3.请找到一条从左下角(1,1)出发经过所有没有障碍物的点各 一次的且最后回到左下角的回路. Input 第一行包含三个整数n,

bzoj 3261: 最大异或和 (可持久化trie树)

3261: 最大异或和 Time Limit: 10 Sec  Memory Limit: 512 MB Description 给定一个非负整数序列 {a},初始长度为 N.       有   M个操作,有以下两种操作类型: 1 .A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1.2 .Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得: a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少. Inp