jzoj5141 【NOI2017模拟6.12】说无可说

传送门:https://jzoj.net/senior/#main/show/5141

【题目大意】

给出n个字符串,求有多少组字符串之间编辑距离为1~8。

n<=200,∑|S| <= 10^6

【题解】

首先找编辑距离有一个n^2的dp,由于发现只找小于等于8的,所以搜旁边16个状态即可。

复杂度O(n^2|S| * 16)

# include <vector>
# include <stdio.h>
# include <iostream>
# include <string.h>
# include <algorithm>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

const int N = 200 + 10, M = 1e6 + 10, AN = 10;
const int mod = 1e9 + 7;

int n, len[M], ans[AN];
vector<char> a[N];
char str[M];

int u, v;
int dp[2][M];
inline int f(int i, int j) {
    if(i == 0) return j;
    if(j == 0) return i;
    if(j < max(1, i-8) || j > min(len[v], i+8)) return 1e9;
    return dp[i&1][j];
}

inline void fin(int i, int j, int s) {
    dp[i&1][j] = s;
}

inline int gans() {
    for (int i=1; i<=len[v] || i<=len[u]; ++i) fin(0, i, 0), fin(1, i, 0);
    for (int i=1; i<=len[u]; ++i)
        for (int j=max(1, i-8), jto = min(i+8, len[v]); j<=jto; ++j) {
            fin(i, j, min(f(i-1, j), f(i, j-1)) + 1);
            if(a[u][i-1] != a[v][j-1]) fin(i, j, min(f(i, j), f(i-1, j-1) + 1));
            else fin(i, j, min(f(i, j), f(i-1, j-1)));
        }
    return f(len[u], len[v]);
}

int main() {
//    freopen("say.in", "r", stdin);
//    freopen("say.out", "w", stdout);
    cin >> n;
    for (int i=1; i<=n; ++i) {
        scanf("%s", str);
        len[i] = strlen(str);
        for (int j=0; str[j]; ++j) a[i].push_back(str[j]);
    }
    for (int i=1, tem; i<=n; ++i) {
        for (int j=i+1; j<=n; ++j) {
            u = i, v = j;
            tem = gans();
            if(tem >= 1 && tem <= 8) ++ ans[tem];
        }
    }

    for (int i=1; i<=8; ++i) cout << ans[i] << ‘ ‘;
    cout << endl;
    return 0;
}

当然,过不了,有60分。

所以考虑dp有很多空余状态,改成dfs加剪枝就可以过了。。

# include <vector>
# include <stdio.h>
# include <iostream>
# include <string.h>
# include <algorithm>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

const int N = 200 + 10, M = 1e6 + 10, AN = 10;
const int mod = 1e9 + 7;

int n, len[M], ans[AN];
vector<char> a[N];
char str[M];

# define ABS(x) ((x) > 0 ? (x) : -(x))

int tem;
inline void solve(int u, int v, int cur_u, int cur_v, int cnt) {
    if(cnt + ABS(len[v] - len[u] - (cur_v - cur_u)) >= tem) return;
    while(cur_u < len[u] && cur_v < len[v]) {
        if(a[u][cur_u] != a[v][cur_v]) {
            solve(u, v, cur_u+1, cur_v, cnt+1);
            solve(u, v, cur_u, cur_v+1, cnt+1);
            solve(u, v, cur_u+1, cur_v+1, cnt+1);
            return ;
        }
        ++cur_u, ++cur_v;
    }
    if(cur_u == len[u]) tem = min(tem, cnt + len[v] - cur_v);
    if(cur_v == len[v]) tem = min(tem, cnt + len[u] - cur_u);
}

int main() {
//    freopen("say.in", "r", stdin);
//    freopen("say.out", "w", stdout);
    cin >> n;
    for (int i=1; i<=n; ++i) {
        scanf("%s", str);
        len[i] = strlen(str);
        for (int j=0; str[j]; ++j) a[i].push_back(str[j]);
    }
    for (int i=1; i<=n; ++i) {
        for (int j=i+1; j<=n; ++j) {
            tem = 9;
            solve(i, j, 0, 0, 0);
            ++ ans[tem];
        }
    }

    for (int i=1; i<=8; ++i) cout << ans[i] << ‘ ‘;
    cout << endl;

    return 0;
}

这里dfs的时候需要注意一点,要一段一段跳,不能一格一格跳,会T。。

时间: 2024-10-05 04:45:38

jzoj5141 【NOI2017模拟6.12】说无可说的相关文章

jzoj5142 【NOI2017模拟6.12】看无可看

传送门:https://jzoj.net/senior/#main/show/5142 [题目大意] 给出n个数,a[1]...a[n],称作集合S,求 其中f[i] = 2f[i-1] + 3f[i-2],给出f[0],f[1].mod 99991 n<=100000 [题解] 暴力dp,用矩阵作为存储值,复杂度O(n^2) # include <ctype.h> # include <stdio.h> # include <assert.h> # includ

Cisco PT模拟实验(12) 路由器静态路由的配置

Cisco PT模拟实验(12) 路由器静态路由的配置 实验目的: 掌握静态路由的配置方法和应用 掌握路由选择表中的路由描述 熟悉路由选择和分组转发的原理及过程 实验背景: 某公司除总部外,另有一处分部,并且都有一个独立的局域网,为了使公司各部之间能相互通信,共享资源.每个出口利用一台路由器进行连接,两台路由器间公司申请了一条DDN专线(数字数据网)进行相连,要求做适当配置实现相互访问. 技术原理: 路由器属于网络层设备,能够根据IP数据报的首部信息,选择一条最佳路径(这一过程称为"路由选择&q

JZOJ.5285【NOI2017模拟8.16】排序

Description Input Output Sample Input 5 2 1 5 3 4 Sample Output 5 4 3 1 2 Data Constraint Hint 感觉像是某年NOIP的双栈排序的弱化版...... 这题要求字典序最大,我们采用贪心做法,我们可以证明这是正确的. 考虑每一位的数字,我们尽可能地让它大,很明显第一位一定能保证是最大值. 那么对于第二位我们当然想让它为第二大的数字,如果这个数字不在栈里面,那么我们可以等待它进栈后再弹出,但如果已经在栈里面,但

JZOJ.5264【NOIP2017模拟8.12】化学

Description Input Output Sample Input 3 10 1 2 10 Sample Output 5 Data Constraint Hint 搜索.考虑到m很大,我们不得不从n下手,但240无法满足要求,我们可以采取折半搜索. 先搜前20个记录所有220的方案情况,再搜索后面20个,把全部方案数分别记录到两个数组里,从小到大排个序,然后用指针维护统计答案就可以了. 因为要两个情况所耗费的体力值不大于m,所以我们可以固定第一个数组的指针i,第二个数组指针j从大到小找

模拟1----1/12

A: 答案-3249 求第一个阶乘位数>=10000的正整数 公式:位数=log10(1)+log10(2)+...+log10(n)+1 再取整 举个例子:log(123)=2.08991 取整+1=3: n!=1*2*3*.....*n;    lg(n!)=lg(2)+......lg(n); 1 int main() 2 { 3 double s=0; 4 for(int i=1;;i++){ 5 s+=log10(i); 6 if(int (s+1)>=10000){ 7 cout&

[jzoj]4216.【NOIP2015模拟9.12】平方和

Link https://jzoj.net/senior/#main/show/4216 Description 给出一个N个整数构成的序列,有M次操作,每次操作有一下三种: ①Insert Y X,在序列的第Y个数之前插入一个数X: ②Add L R X,对序列中第L个数到第R个数,每个数都加上X: ③Query L R,询问序列中第L个数到第R个数的平方和. Solution 我不会告诉你这道题我打了10000+byte,并且改了2个月,50多个小时,删掉代码重打了5次.这道题用splay来

【bzoj4552】【Tjoi2016&amp;Heoi2016】【NOIP2016模拟7.12】排序

题目 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q 位置上的数字. 分析 二分答案, 把二分出的ans与原序列比较,小于ans的数改为-1,大于ans的数改为1. 对于输入的每一个修改,用线段树来处理. 最后求

SPTGROUP.DrillBench.v5.0 钻井及完井工程设计模拟软件

1.钻井及完井工程设计模拟软件包 Drillbench.Suite.v6.1 1CDDrillbench.Suite.v6.1 1CD 钻井及完井工程设计模拟软件包 动态模拟是钻井作业中必要的工作,在投诸运营之前,会复制一个真正的钻井作业,并提供高精度的稳态模型.Drillbench提供了一个用户友好的操作界面,适用于所有的钻井工程师.该... 2.Schlumberger Drilling Office 2008.1 1CD(综合钻井工程设计软件)Schlumberger Drilling O

简单数据结构之栈模拟

1 /************************************************************************************** 2 * Function : 模拟栈 3 * Create Date : 2014/04/23 4 * Author : NTSK13 5 * Email : [email protected] 6 * Copyright : 欢迎大家和我一起交流学习,转载请保持源文件的完整性. 7 * 任何单位和个人不经本人允许不得