zoukankan      html  css  js  c++  java
  • 插件与App的跳转,及路由的关系

    在SDK中 无法直接跳App 的界面,这个时候需要使用 路由,或者通过 NSClassFromString 的

    presentViewController 来跳转。

    直接贴代码: 

    UIViewController *VC = [NSClassFromString(@"WZFullmotionPagesController") new];
    
        id prepareAction = ^(void (^ _Nonnull success)(void)) {
            
            UIViewController *VC1 = [NSClassFromString(@"WZServiceSelectController") new];
            id prepareAction1 = ^(void) {
                if (success) success();
            };
            [VC1 setValue:prepareAction1 forKey:@"defaultSetCMCCallBack"];
    
            [self.navigationController pushViewController:VC1 animated:YES];
            [VC1.view setNeedsDisplay];
        };
        
        [VC setValue:prepareAction forKey:@"prepareAction"];
        [self presentViewController:VC animated:YES completion:nil];

    有时候需要回调,可以再回调里 继续添加跳转 

    路由的使用:
    有的控制器 需要先添加路由的方式,再根据plist 来调用

    - (void)router:(WPKRouterAction *)action setParam:(WPKRParamModelBase *)param block:(WPKRouterBlock)block
    {
        //这里可以处理逻辑
        NSDictionary *dict = (NSDictionary *)param;
        WPKNameCamSetingController *VC = [[WPKNameCamSetingController alloc] init];
        VC.deviceMac = dict [@"deviceMac"];
        VC.deviceModel = dict [@"deviceModel"];
        VC.nameCamsSetingType = dict[@"nameCamsSetingType"];
        VC.progress = dict[@"progress"];
        VC.saveBtnStr = dict[@"saveBtnStr"];
        VC.routeAddress = dict[@"routeAddress"];
        VC.routeAguments = dict[@"routeAguments"];
        WPKRCallbackModel *callbackModel = [[WPKRCallbackModel alloc] init];
        VC.NameCamSetingFinishClick = ^(NSString * _Nonnull code){
            callbackModel.object = code;
            block(callbackModel);
        };
        [[WPKUIUtils topViewController].navigationController pushViewController:VC animated:YES];
    
    }

    路由的具体实现

    //
    //  WPKRouter.m
    //  WZPlatformKit
    //
    //  Created by abc on 2019/4/30.
    //  Copyright © 2019 米家. All rights reserved.
    //
    
    #import "WPKRouter.h"
    #import "WPKRCallbackModel.h"
    #import "WPKRParamModelBase.h"
    #import "WPKRouterAction.h"
    #import "WPKRouterUtil.h"
    #import "WPKSerializationHelper.h"
    #import <objc/runtime.h>
    #import "WPKRouterPool.h"
    
    //router内部存储actionModel时,给参数增加识别码,用于业务结束操作时回传该识别码,注销actionmodel
    static NSString * const WPK_ROUTER_KEY_STRING = @"WPK_ROUTER_KEY_STRING";
    
    static NSString * const WPK_ROUTER_CLASS_PREFIX = @"WPK_router_executor_";
    static NSString * const WPK_ROUTER_FUNC_PREFIX = @"retriveSelectorFor_";
    
    
    typedef void (^WPKRouterH5Block)(WPKRCallbackModel *result, WPKRParamModelBase *modleBase);
    
    @interface WPKRouter() 
    @property (atomic, strong) WPKRouterAction *actionModel;
    
    /**
     存储 WPKRouterAction 对象
     */
    @property (nonatomic,strong)NSMutableArray * actionModelArray;
    @property (nonatomic,strong)NSMutableDictionary * actionModeKeyDic;
    
    @end
    
    @implementation WPKRouter
    #pragma mark - life cycles
    + (id)allocWithZone:(struct _NSZone *)zone
    {
        return [WPKRouter sharedInstance];
    }
    
    + (instancetype)sharedInstance
    {
        static WPKRouter *inst;
        static dispatch_once_t once_t;
        dispatch_once(&once_t, ^{
            inst = [[super allocWithZone:NULL] init];
        });
        return inst;
    }
    
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            _util = [[WPKRouterUtil alloc] init];
        }
        return self;
    }
    
    #pragma mark - public
    
    - (id)callCls:(NSString *)cls sel:(NSString *)sel params:(NSArray *)params
    {
        //    获取类名
        NSString *target = [NSString stringWithFormat:@"%@%@", WPK_ROUTER_CLASS_PREFIX, cls];
        Class c = NSClassFromString(target);
        if (c) {//        获取函数名获取器
            NSString *action = [NSString stringWithFormat:@"%@%@", WPK_ROUTER_FUNC_PREFIX, sel];
            SEL objSel = NSSelectorFromString(action);
            NSObject * obj = [[c alloc] init];
            if ([obj respondsToSelector:objSel]) {
                //            警告!!!此处认为router框架增加的方法固定返回SEL类型,util方法返回字符串
                
                SEL realSel = NSSelectorFromString([WPKRouterUtil performObject:obj selector:objSel withArguments:@[sel]]);
                NSObject *realObj = (NSObject *)[WPKRouterPool excutorForPaths:cls, sel, nil];
                
                //            查看路由池是否有对应的对象
                if (realObj && realSel && [realObj respondsToSelector:realSel]) {
                    id res = [WPKRouterUtil performObject:obj selector:realSel withArguments:params];
                    return res;
                } else if (realSel && [obj respondsToSelector:realSel]) {
                    //路由池无对象则使用新建的子类对象
                    id res = [WPKRouterUtil performObject:obj selector:realSel withArguments:params];
                    return res;
                } else {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wformat"
                    WPKInfoLog(@"ERROR: router can't find selector: %s", realSel);
    #pragma clang diagnostic pop
                }
            } else {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wformat"
                WPKInfoLog(@"ERROR: router can't find selector: %s", objSel);
    #pragma clang diagnostic pop
            }
        }
        return nil;
    }
    
    #pragma mark - private
    - (void)pushActionModel:(WPKRouterAction*)model routerKey:(NSString *)routerKey
    {
        @synchronized(self) {
            if (model.excutor && model.catchCallBack) {
                [self.actionModelArray addObject:model];
                self.actionModeKeyDic[routerKey] = model;
            }
        }
    }
    
    - (void)popActionModelWithRouterKey:(NSString *)routerKey
    {
        @synchronized(self) {
            WPKRouterAction * model = self.actionModeBlockDic[routerKey];
            if (model.catchCallBack) {
                [self.actionModelArray removeObject:model];
                [self.actionModeKeyDic removeObjectForKey:routerKey];
            }
        }
    }
    
    #pragma mark - publics
    
    /**
     *  H5调用WPK协议入口
     *
     *  @param url url
     */
    - (void)startUrl:(NSURL *)url
    {
        //通过mwap执行参数回调
        WPKRouterH5Block block = ^(WPKRCallbackModel *result, WPKRParamModelBase *modleBase) {
            if (result.object) {
                NSMutableDictionary *dict = [NSMutableDictionary dictionary];
                result.object != nil ? [dict setObject:result.object forKey:@"content"] : nil;
                modleBase.flagId != nil ? [dict setObject:modleBase.flagId forKey:@"flagId"] : nil;
                [[WPKRouter sharedInstance] startModuleSecoupled:@"mwap" path:@"servicecallback" paramDict:dict block:nil];
            }
        };
        [self callNativeFromH5Url:url block:block];
        
    }
    
    - (void)startUrl:(NSURL *)url callback:(WPKRouterBlock)callback
    {
        WPKRouterH5Block block = ^(WPKRCallbackModel *result, WPKRParamModelBase *modleBase) {
            callback(result);
        };
        [self callNativeFromH5Url:url block:block];
    }
    
    
    //H5专用
    - (void)callNativeFromH5Url:(NSURL *)url block:(WPKRouterH5Block)block
    {
        NSString *module = [_util getModuleStrFromUrl:url];//module
        NSString *path = [_util getPathStrFromUrl:url];    //path
        NSString *paramStr = [_util getParamStrFromUrl:url];    //param
    
        WPKRouterAction *actionModel = [_util getActionFromModule:module path:path];
        
        if (![actionModel excutor]) {
            [self handleOldVersionWithUrl:url];//兼容老的WPK协议跳转
            return;
        }
        
        if (!module || !path ) {
            WPKRouterBlock temp = ^(WPKRCallbackModel *result) {
                block(result, nil);
            };
            if (path) {
                [_util goto404Error:[module stringByAppendingPathComponent:path] withBlock:temp];
            }
            return;
        }
        
        NSDictionary *paramDic = [_util getParametersDictionaryWithParams:paramStr];
        
        WPKRParamModelBase*param;
        if ([actionModel.in length] > 0) {
            Class paramClass = NSClassFromString(actionModel.in);
            param = [[paramClass alloc] init];
        } else {
            //h5不设置入参,只需要flagID
            param = [[WPKRParamModelBase alloc] init];
        }
        if ([param isKindOfClass:[WPKRParamModelBase class]]) {
            param.originURL = url;
        }
        [[WPKSerializationHelper sharedInstance] importDictionary:paramDic toObject:param];
        
        WPKRouterBlock blocktemp = ^(WPKRCallbackModel *result) {
            block(result, param);
        };
        [self startModule:module path:path param:param block:blocktemp];
    }
    
    - (void)startModule:(NSString *)kWPKRouter_M
                  path:(NSString *)kWPKRouter_M_P
                 param:(WPKRParamModelBase *)param
                 block:(WPKRouterBlock)block
    {
        WPKInfoLog(@">> WPKRouter: %@/%@ param: %@",kWPKRouter_M, kWPKRouter_M_P, param );
        WPKRouterAction *WPKActionModel = [_util getActionFromModule:kWPKRouter_M
                                                                path:kWPKRouter_M_P];
        if (!param) {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored  "-Wincompatible-pointer-types"
            param = [NSObject new];
    #pragma clang diagnostic pop
        }
        param.routerKey = [self getDateNow];
        [self pushActionModel:WPKActionModel routerKey:param.routerKey];
        [self handleAction:WPKActionModel paramModel:param block:block];
    }
    
    - (void)startModuleSecoupled:(NSString *)kWPKRouter_M
                            path:(NSString *)kWPKRouter_M_P
                       paramDict:(NSDictionary *)paramDict
                           block:(WPKRouterBlock)block
    {
        WPKRouterAction *WPKActionModel = [_util getActionFromModule:kWPKRouter_M
                                                                path:kWPKRouter_M_P];
        WPKActionModel.navigationController = self.navigationController;
        if (!paramDict) {
            paramDict = [NSDictionary new];
        }
        paramDict.routerKey = [self getDateNow];
        [self pushActionModel:WPKActionModel routerKey:paramDict.routerKey];
        WPKRParamModelBase*paramModel;
        if ([WPKActionModel.in length] > 0) {
            Class paramClass = NSClassFromString(WPKActionModel.in);
            paramModel = [[paramClass alloc] init];
        } else {
            //h5不设置入参,只需要flagID
            paramModel = [[WPKRParamModelBase alloc] init];
        }
        
        if ([paramModel respondsToSelector:@selector(analyzeWPKRouterModelWithModelInfo:)]) {
            [paramModel analyzeWPKRouterModelWithModelInfo:paramDict];
        } else if ([paramModel isKindOfClass:[NSDictionary class]]) {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored  "-Wincompatible-pointer-types"
            paramModel = paramDict;
    #pragma clang diagnostic pop
        } else {
            [[WPKSerializationHelper sharedInstance] importDictionary:paramDict toObject:paramModel];
        }
        /*
         由于 mj_setKeyValues 方法不能将动态添加的属性转到相应的模型中所以进行如此修改
         */
        paramModel.routerKey = paramDict.routerKey;
        [self handleAction:WPKActionModel paramModel:paramModel block:block];
    }
    
    - (id)readDataModuleSecoupled:(NSString *)kWPKRouter_M
                             path:(NSString *)kWPKRouter_M_P
                        paramDict:(NSDictionary *)paramDict
    {
        WPKRouterAction *WPKActionModel = [_util getActionFromModule:kWPKRouter_M
                                                                path:kWPKRouter_M_P];
        WPKActionModel.navigationController = self.navigationController;
        if (!paramDict) {
            paramDict = [NSDictionary new];
        }
        paramDict.routerKey = [self getDateNow];
        [self pushActionModel:WPKActionModel routerKey:paramDict.routerKey];
        WPKRParamModelBase*paramModel;
        if ([WPKActionModel.in length] > 0) {
            Class paramClass = NSClassFromString(WPKActionModel.in);
            paramModel = [[paramClass alloc] init];
        } else {
            //h5不设置入参,只需要flagID
            paramModel = [[WPKRParamModelBase alloc] init];
        }
        
        if ([paramModel respondsToSelector:@selector(analyzeWPKRouterModelWithModelInfo:)]) {
            [paramModel analyzeWPKRouterModelWithModelInfo:paramDict];
        } else if ([paramModel isKindOfClass:[NSDictionary class]]) {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored  "-Wincompatible-pointer-types"
            paramModel = paramDict;
    #pragma clang diagnostic pop
        } else {
            [[WPKSerializationHelper sharedInstance] importDictionary:paramDict toObject:paramModel];
        }
        /*
         由于 mj_setKeyValues 方法不能将动态添加的属性转到相应的模型中所以进行如此修改
         */
        paramModel.routerKey = paramDict.routerKey;
        return [self handleAction:WPKActionModel paramModel:paramModel];
    }
    
    - (NSString *)composeURLForModule:(NSString *)kWPKRouter_M
                                 path:(NSString *)kWPKRouter_M_P
                                param:(WPKRParamModelBase *)param
                         iswithScheme:(BOOL)isWithScheme {
        
        NSString *json = @"";
        if (param) {
            json = [param toJsonString];
        }
        NSString *scheme = [NSString stringWithFormat:@"%@://", kWPKRouter_scheme];
        NSString *url = [NSString stringWithFormat:@"%@%@/%@?%@=%@",
                         isWithScheme?scheme:@"",
                         kWPKRouter_M,
                         kWPKRouter_M_P?kWPKRouter_M_P:kWPKRouter_default_path,
                         kWPKRouter_paramName,
                         [json stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]
                         ];
        
        return url;
    }
    /**
     *   解析url数据
     *
     *  @param urlString url
     *
     *  @return 返回地址中存在的参数数据模型
     */
    - (nullable WPKRParamModelBase *)parseParamModelWithUrl:(NSString *)urlString;
    {
        NSURL *url = [NSURL URLWithString:urlString];
        
        //module
        NSString *module = [_util getModuleStrFromUrl:url];
        if (module == nil) {
            return nil;
        }
        //path
        NSString *path = [_util getPathStrFromUrl:url];
        if (path == nil) {
            return nil;
        }
        //param
        NSString *paramStr = [_util getParamStrFromUrl:url];
        
        WPKRouterAction *actionModel = [_util getActionFromModule:module path:path];
        if (paramStr && actionModel.in) {
            NSDictionary *paramDic = [_util getParametersDictionaryWithParams:paramStr];
            WPKRParamModelBase *model = [(WPKRParamModelBase *) [NSClassFromString(actionModel.in) alloc] init];
            [[WPKSerializationHelper sharedInstance] importDictionary:paramDic toObject:model];
            return model;
        }
        return nil;
    }
    
    -(void)callbackAction:(WPKRouterBlock)block result:(id)obj paramIn:(NSObject *)inModel error:(NSError *)error
    {
        NSString *key=@"";
        
        if ([inModel.routerKey length] > 0) {
            key = inModel.routerKey;
        }
        if ([self.actionModeBlockDic.allKeys containsObject:key]) {
            [self popActionModelWithRouterKey:key];
        }
        
        WPKRCallbackModel *model = [[WPKRCallbackModel alloc]init];
        if ([obj isKindOfClass:[NSString class]]) {
            model.object = @{@"result":obj};
        } else {
            model.object = obj;
        }
        model.code = (int)error.code;
        model.errorMessage=error.localizedDescription;
        if (block) {
            block(model);
        }
        
    }
    - (void)callbackAction:(WPKRouterBlock)block result:(id)obj
    {
        [self callbackAction:block result:obj paramIn:nil];
    }
    
    - (void)callbackAction:(WPKRouterBlock)block result:(id)obj paramIn:(NSObject *)inModel
    {
        [self callbackAction:block result:obj paramIn:inModel error:nil];
    }
    
    - (BOOL)canCheckModel:(NSString *)kWPKRouter_M path:(NSString *)kWPKRouter_M_P
    {
        return [self canCheckModel:[_util getActionFromModule:kWPKRouter_M path:kWPKRouter_M_P]];
    }
    
    - (BOOL)canCheckUrl:(NSURL *)url
    {
        return [self canCheckModel:[_util getActionFromModule:[_util getModuleStrFromUrl:url] path:[_util getPathStrFromUrl:url]]];
    }
    
    - (BOOL)canCheckModel:(WPKRouterAction *)actionModel
    {
        if (actionModel == nil || actionModel.excutor.length == 0) {
            return NO;
        }
        
        Class class = NSClassFromString(actionModel.excutor);
        if (class == nil || class == [NSNull null]) {
            return NO;
        }
        
        return YES;
    }
    #pragma mark - 检测WPK协议是否存在
    
    - (BOOL)startCheckSupportURL:(NSURL *)url
    {
        //module
        NSString *module = [_util getModuleStrFromUrl:url];
        //path
        NSString *path = [_util getPathStrFromUrl:url];
        //param
        NSString *paramStr = [_util getParamStrFromUrl:url];
        
        WPKRouterAction *actionModel = [_util getActionFromModule:module path:path];
        WPKRParamModelBase*param;
        if ([actionModel.in length] > 0) {
            Class paramClass = NSClassFromString(actionModel.in);
            param = [[paramClass alloc] init];
        } else {
            //h5不设置入参,只需要flagID
            param = [[WPKRParamModelBase alloc] init];
        }
        
        NSDictionary *paramDic = [_util getParametersDictionaryWithParams:paramStr];
        [[WPKSerializationHelper sharedInstance] importDictionary:paramDic toObject:param];
        
        return [self startCheckSupportModule:module path:path param:param];
    }
    
    - (BOOL)startCheckSupportURLString:(NSString *)urlString{
        
        if (!urlString || ![urlString isKindOfClass:[NSString class]] || ![urlString hasPrefix:@"WPK://"]) {
            return NO;
        }
        
        NSURL *url = [NSURL URLWithString:urlString];
        if (!url) {
            urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    //        urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
            url = [NSURL URLWithString:urlString];
        }
        
        return [self startCheckSupportURL:url];
    }
    
    - (BOOL)startCheckSupportModule:(NSString *)kWPKRouter_M
                               path:(NSString *)kWPKRouter_M_P
                              param:(WPKRParamModelBase*)param
    {
        WPKRouterAction *WPKActionModel = [_util getActionFromModule:kWPKRouter_M
                                                                path:kWPKRouter_M_P];
        if (![WPKActionModel excutor]) {
            return NO;
        } else {
            //参数判断
            if ([WPKActionModel.in length] > 0) {
                Class paramClass = NSClassFromString(WPKActionModel.in);
                if (param && ![param isKindOfClass:paramClass]) {
                    return NO;
                }
            }
            return YES;
        }
    }
    
    #pragma mark - private method
    
    - (void)handleAction:(WPKRouterAction *)action
              paramModel:(NSObject*)paramModel
                   block:(WPKRouterBlock)block
    {
        if (![action excutor]) {
            [_util goto404Error:[action.moduleName stringByAppendingPathComponent:action.pathName] withBlock:block];
        } else {
            if ([paramModel isKindOfClass:[WPKRParamModelBase class]]) {
                action.url = [(WPKRParamModelBase*)paramModel originURL];
            }
            if ([action.in length] > 0) {
                Class paramClass = NSClassFromString(action.in);
                if (paramModel && ![paramModel isKindOfClass:paramClass]) {
                    [_util goto404Error:[action.moduleName stringByAppendingPathComponent:action.pathName] withBlock:block];
                    return;
                }
            }
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored  "-Wincompatible-pointer-types"
            [action doActionWithParam:paramModel block:block];
    #pragma clang diagnostic pop
        }
        
        self.actionModel = action;
    }
    
    
    - (id)handleAction:(WPKRouterAction *)action
              paramModel:(NSObject *)paramModel
    {
        self.actionModel = action;
        if (![action excutor]) {
            [_util goto404Error:[action.moduleName stringByAppendingPathComponent:action.pathName] withBlock:nil];
        } else {
            if ([paramModel isKindOfClass:[WPKRParamModelBase class]]) {
                action.url = [(WPKRParamModelBase*)paramModel originURL];
            }
            if ([action.in length] > 0) {
                Class paramClass = NSClassFromString(action.in);
                if (paramModel && ![paramModel isKindOfClass:paramClass]) {
                    [_util goto404Error:[action.moduleName stringByAppendingPathComponent:action.pathName] withBlock:nil];
                    return nil;
                }
            }
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored  "-Wincompatible-pointer-types"
            return [action doActionWithParam:paramModel];
    #pragma clang diagnostic pop
        }
        return nil;
    }
    
    #pragma mark - 失败回调
    
    - (void)handleOldVersionWithUrl:(NSURL *)url
    {
        /*  WPK://qrcode:1#feedId:o_1462533315926565
         WPK://c-2345
         */
        
        // 浏览器对第二个#进行了混乱解析,
        NSString *newAbsoluteString =  [url.absoluteString stringByReplacingOccurrencesOfString:@"%23" withString:@"#"];
        NSDictionary *dict = @{@"WPKUrl":newAbsoluteString.length?newAbsoluteString:@""};
        [self startModuleSecoupled:@"qrcode" path:@"qrcodeTool" paramDict:dict block:nil];
    }
    
    - (NSMutableArray *)actionModelArray
    {
        if (!_actionModelArray) {
            _actionModelArray = [NSMutableArray arrayWithCapacity:0];
        }
        if (_actionModelArray.count >= 19) {
            NSArray * keyArr = self.actionModeBlockDic.allKeys;
            for (NSString * key in keyArr) {
                if ([self.actionModeBlockDic[key] isEqual:_actionModelArray.firstObject]) {
                    [_actionModelArray removeObject:_actionModelArray.firstObject];
                    [self.actionModeBlockDic removeObjectForKey:key];
                    break;
                }
            }
        }
        return _actionModelArray;
    }
    
    - (NSMutableDictionary *)actionModeBlockDic
    {
        if (!_actionModeKeyDic) {
            _actionModeKeyDic = [NSMutableDictionary dictionary];
        }
        return _actionModeKeyDic;
    }
    
    - (NSString *)getDateNow
    {
        NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];
        NSTimeInterval a=[dat timeIntervalSince1970]*1000;
        NSString *timeString = [NSString stringWithFormat:@"%f", a];
        return timeString;
    }
    
    @end
    
    @implementation NSObject(WPKRouterExtension)
    - (NSString *)routerKey
    {
        return objc_getAssociatedObject(self, (__bridge const void *)(WPK_ROUTER_KEY_STRING));
    }
    
    - (void)setRouterKey:(NSString *)routerKey
    {
        objc_setAssociatedObject(self, (__bridge const void *)(WPK_ROUTER_KEY_STRING), routerKey, OBJC_ASSOCIATION_COPY);
    }
    @end

    App 调用插件代码 及传参

    //    [[WPKRouter sharedInstance] startModuleSecoupled:WPK_kPlatformName path:wpk_kNameCamSetting paramDict:@{@"deviceMac":@"2CAA8E21AEC7",@"deviceModel":@"XXXC1-JZ",@"nameCamsSetingType":WPK_Type_bding,@"routeAddress":@"namecamseting",@"progress":@"0.75"} block:^(WPKRCallbackModel *result) {
    //    }];

    plist文件 设置

    基础架构

  • 相关阅读:
    UVA 1600
    P3366 【模板】最小生成树(堆优化prim)
    P2414 [NOI2011]阿狸的打字机
    P2322 [HNOI2006]最短母串问题
    P4052 [JSOI2007]文本生成器
    P4824 [USACO15FEB]Censoring (Silver) 审查(银)&&P3121 [USACO15FEB]审查(黄金)Censoring (Gold)
    P3966 [TJOI2013]单词
    P2444 [POI2000]病毒
    P3294 [SCOI2016]背单词
    P2922 [USACO08DEC]秘密消息Secret Message
  • 原文地址:https://www.cnblogs.com/tangyuanby2/p/12373540.html
Copyright © 2011-2022 走看看