函数依赖的闭包生成

如A,B,C -> D, E

输入:ABC DE
直到End结束
再次输入集合,输出该集合的闭包。

实现: 查询每次都是扫面前面的所有函数依赖,直到一次循环下来闭包不再更新。
使用细节:二进制枚举子集,for(int i = s; i; i = (i-1)&s)

#include <cstdio>
#include <algorithm>
#include <cstring>
#define CLS memset
#define r0 return 0

using ll = long long;
using namespace std;
const int N = 1e4 + 9;
const int M = 30;
char s[N][M], t[N][M], q[M];
int cnt;
ll l[N], r[N];
bool judge[M];

bool End (char a, char b, char c) {
    if (a != 'E' && a != 'e') r0;
    if (b != 'N' && b != 'n') r0;
    if (c != 'D' && c != 'd') r0;
    return 1;
}

bool AZ (char a) {return a <= 'Z' && a >= 'A';}

ll trans (char s[]) {
    bool vis[M]; CLS(vis, 0, sizeof vis);
    for (int i = 0 ; s[i]; i++) vis[s[i] - 'A'] = 1;
    ll tmp = 0;
    for (int i = 0; i < 26; i++) tmp *= 2, tmp += vis[i];
    return tmp;
}

void init (char s[], char t[], int cnt) { l[cnt] = trans(s); r[cnt] = trans(t);}

void out(ll v, char ed = '\n') {
    if(v == 0) { printf("NULL%c", ed); return ;}
    ll tmp = 1LL<<25;
    for (int i = 0; i < 26; i++) {
        if((v&tmp) == tmp) printf("%c", 'A' + i);
        tmp >>= 1;
    } printf("%c", ed);
}

ll solve(ll tmp){
    bool vis[N]; for (int i = 0; i < cnt; i++) vis[i] = 0;
    int tot = 0, id = 0;
    while (tot <= cnt + 1) {
        if (!vis[id] && (tmp & l[id]) == l[id]) {
            tmp |= r[id]; tot = 0; vis[id] = 1;
        } tot ++;
        id = (id + 1)%cnt;
    } return tmp;
}

void in() {
    cnt = 0;
    while (~scanf("%s", s[cnt])) {
        if (End(s[cnt][0], s[cnt][1], s[cnt][2])) break;
        scanf("%s", t[cnt]);
        for (int i = 0; s[cnt][i]; i++) if (!AZ(s[cnt][i])) puts("别输入除大写字母以外的字符, 请关闭重来");
        for (int i = 0; t[cnt][i]; i++) if (!AZ(t[cnt][i])) puts("别输入除大写字母以外的字符, 请关闭重来");
        sort(s[cnt], s[cnt]+strlen(s[cnt])); sort(t[cnt], t[cnt]+strlen(t[cnt]));
        init(s[cnt], t[cnt], cnt);
        printf("第%d个函数:%s->%s\n", cnt+1, s[cnt], t[cnt]); cnt ++;
    }
}

void query() {
    puts("请输入属性集求闭包");
    while (~scanf("%s", q)) {
        if (End(q[0], q[1], q[2])) break;
        printf("(%s)+ : ", q); out(solve(trans(q)));
    }
}

void dfs(int id, ll v) {
    if(id == 26) {
        ll s = solve(v);
        out(v, ' '); printf("-> {");
        for(int i = s; i; i = (i-1)&s) out(i, ',');
        puts("NULL}\n");
    } else {
        if(judge[id]) dfs(id+1, v<<1|1);
        dfs(id+1, v<<1);
    }
}

void fuck() {
    CLS(judge, 0, sizeof judge);
    for (int i = 0; i < cnt; i++) {
        for (int j = 0; s[i][j]; j++) judge[s[i][j] - 'A'] = 1;
        for (int j = 0; t[i][j]; j++) judge[s[i][j] - 'A'] = 1;
    } dfs(0, 0);
}

int main(){
    printf("请输入函数依赖,请使用空格代替箭头\n");
    in(); query(); return fuck(), 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值